@saasicat/core 1.0.0-rc.15 → 1.0.0-rc.17
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/.build-stamp +1 -1
- package/dist/index.cjs +319 -0
- package/dist/index.d.cts +867 -84
- package/dist/index.d.ts +867 -84
- package/dist/index.js +304 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -473,6 +473,275 @@ interface UpdateMarketingProjectionData {
|
|
|
473
473
|
highlight?: boolean;
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
/** The address lines a party is named with. Every one of them may be unknown. */
|
|
477
|
+
interface PartyAddress {
|
|
478
|
+
/** Street and number. */
|
|
479
|
+
addressLine1: string | null;
|
|
480
|
+
/** A second line, such as a building or a c/o. */
|
|
481
|
+
addressLine2: string | null;
|
|
482
|
+
postalCode: string | null;
|
|
483
|
+
city: string | null;
|
|
484
|
+
/** ISO 3166-1 alpha-2, upper case. */
|
|
485
|
+
country: string | null;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* What names a legal entity: the name it is registered under and the
|
|
489
|
+
* identifiers its tax office gave it.
|
|
490
|
+
*
|
|
491
|
+
* For a subscriber these are the party a contract was concluded with. Under a
|
|
492
|
+
* running contract they change only as a correction of that same entity,
|
|
493
|
+
* recorded with the values it replaced and the reason; contact details change
|
|
494
|
+
* freely.
|
|
495
|
+
*/
|
|
496
|
+
interface LegalIdentity {
|
|
497
|
+
/** The registered name, legal form included. */
|
|
498
|
+
legalName: string;
|
|
499
|
+
/** VAT identification number. */
|
|
500
|
+
vatId: string | null;
|
|
501
|
+
/** The national tax number, where one is stated beside or instead of the VAT id. */
|
|
502
|
+
taxNumber: string | null;
|
|
503
|
+
}
|
|
504
|
+
/** The fields of the legal identity, the ones a correction may change. */
|
|
505
|
+
type SubscriberIdentityField = keyof LegalIdentity;
|
|
506
|
+
/** How a subscriber is reached, which may change at any time. */
|
|
507
|
+
interface SubscriberContact extends PartyAddress {
|
|
508
|
+
/** Where invoices will be sent. */
|
|
509
|
+
invoiceEmail: string | null;
|
|
510
|
+
}
|
|
511
|
+
/** A subscriber's master data, as it stands. */
|
|
512
|
+
type SubscriberDetails = LegalIdentity & SubscriberContact;
|
|
513
|
+
/**
|
|
514
|
+
* What a subscriber is created with.
|
|
515
|
+
*
|
|
516
|
+
* Only the legal name is required. The address, the tax identifiers and the
|
|
517
|
+
* invoice email stay optional until sign-up asks for them and invoicing
|
|
518
|
+
* requires them; an absent or blank value is recorded as unknown.
|
|
519
|
+
*/
|
|
520
|
+
type NewSubscriberDetails = Pick<SubscriberDetails, 'legalName'> & Partial<Omit<SubscriberDetails, 'legalName'>>;
|
|
521
|
+
interface SubscriberRecord extends SubscriberDetails {
|
|
522
|
+
id: string;
|
|
523
|
+
/**
|
|
524
|
+
* Assigned when the subscriber is created and never changed: the number,
|
|
525
|
+
* counted per installation, behind the prefix configured at that moment.
|
|
526
|
+
*/
|
|
527
|
+
customerNumber: string;
|
|
528
|
+
/** The tenant this subscriber is live for, or `null` once it has none. */
|
|
529
|
+
tenantId: string | null;
|
|
530
|
+
/**
|
|
531
|
+
* Created by the migration that gave every existing tenant its subscriber,
|
|
532
|
+
* from the application's own tenant record rather than from what a customer
|
|
533
|
+
* entered.
|
|
534
|
+
*/
|
|
535
|
+
migrated: boolean;
|
|
536
|
+
createdAt: Date;
|
|
537
|
+
updatedAt: Date;
|
|
538
|
+
}
|
|
539
|
+
/** What a repository writes for a new subscriber, every detail already settled. */
|
|
540
|
+
interface CreateSubscriberData extends SubscriberDetails {
|
|
541
|
+
/** The tenant the subscriber is created for and live with. */
|
|
542
|
+
tenantId: string;
|
|
543
|
+
/** Put in front of the assigned number; empty for the number alone. */
|
|
544
|
+
customerNumberPrefix: string;
|
|
545
|
+
}
|
|
546
|
+
/** Contact details to change; a member left out keeps its value. */
|
|
547
|
+
type SubscriberContactChange = Partial<SubscriberContact>;
|
|
548
|
+
/**
|
|
549
|
+
* A change to a subscriber's legal identity, and what the operator declares it
|
|
550
|
+
* to be.
|
|
551
|
+
*
|
|
552
|
+
* SaaSiCat cannot tell a misspelt name from another company taking over, so the
|
|
553
|
+
* operator says which: `correction` for the same legal entity — a typo, a wrong
|
|
554
|
+
* tax identifier, a change of name that entity went through — and `takeover`
|
|
555
|
+
* for another one, which is a transfer rather than an edit and is refused.
|
|
556
|
+
*/
|
|
557
|
+
interface SubscriberIdentityCorrection {
|
|
558
|
+
kind: 'correction' | 'takeover';
|
|
559
|
+
legalName?: string;
|
|
560
|
+
vatId?: string | null;
|
|
561
|
+
taxNumber?: string | null;
|
|
562
|
+
/** Why the identity is corrected. Part of the record. */
|
|
563
|
+
reason: string;
|
|
564
|
+
/** Who corrects it, as an actor tag the audit log would write. */
|
|
565
|
+
correctedBy: string;
|
|
566
|
+
}
|
|
567
|
+
/** Identity values by field, holding only the fields a correction changed. */
|
|
568
|
+
type SubscriberIdentityValues = Partial<LegalIdentity>;
|
|
569
|
+
/** What a correction replaces and what it writes, holding only the fields that move. */
|
|
570
|
+
interface SubscriberIdentityDelta {
|
|
571
|
+
previous: SubscriberIdentityValues;
|
|
572
|
+
corrected: SubscriberIdentityValues;
|
|
573
|
+
}
|
|
574
|
+
/** What a repository writes for a correction the service has accepted. */
|
|
575
|
+
interface SubscriberCorrectionData {
|
|
576
|
+
/** The new values; a field equal to what is stored is not recorded. */
|
|
577
|
+
corrected: SubscriberIdentityValues;
|
|
578
|
+
reason: string;
|
|
579
|
+
correctedBy: string;
|
|
580
|
+
correctedAt: Date;
|
|
581
|
+
}
|
|
582
|
+
/** One correction of a subscriber's legal identity, as it was recorded. */
|
|
583
|
+
interface SubscriberCorrectionRecord {
|
|
584
|
+
id: string;
|
|
585
|
+
subscriberId: string;
|
|
586
|
+
/** The values the correction replaced. */
|
|
587
|
+
previous: SubscriberIdentityValues;
|
|
588
|
+
/** The values it wrote. */
|
|
589
|
+
corrected: SubscriberIdentityValues;
|
|
590
|
+
reason: string;
|
|
591
|
+
correctedBy: string;
|
|
592
|
+
correctedAt: Date;
|
|
593
|
+
}
|
|
594
|
+
/** The outcome of writing a correction: nothing is recorded when no value moved. */
|
|
595
|
+
interface SubscriberCorrectionResult {
|
|
596
|
+
subscriber: SubscriberRecord;
|
|
597
|
+
correction: SubscriberCorrectionRecord | null;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** The payment methods SaaSiCat takes, by the names `config/saas.yaml` uses. */
|
|
601
|
+
type PaymentMethodType = 'card' | 'sepa_debit';
|
|
602
|
+
/**
|
|
603
|
+
* Whom a payment method is set up for. The gateway hands it back unchanged
|
|
604
|
+
* with its confirmation, which is how the confirmation finds its way to the
|
|
605
|
+
* sign-up or the subscriber that asked for it.
|
|
606
|
+
*/
|
|
607
|
+
type PaymentMethodSetupSubject = {
|
|
608
|
+
kind: 'registration';
|
|
609
|
+
pendingRegistrationId: string;
|
|
610
|
+
} | {
|
|
611
|
+
kind: 'subscriber';
|
|
612
|
+
subscriberId: string;
|
|
613
|
+
};
|
|
614
|
+
/** The party the gateway keeps the payment method for: its customer there. */
|
|
615
|
+
interface PaymentMethodHolder {
|
|
616
|
+
/** The legal name, which a direct debit mandate names. */
|
|
617
|
+
name: string;
|
|
618
|
+
/** Where the gateway sends what it sends; `null` lets its form ask. */
|
|
619
|
+
email: string | null;
|
|
620
|
+
address: PartyAddress;
|
|
621
|
+
/**
|
|
622
|
+
* The customer this party already has at the account, from an earlier
|
|
623
|
+
* payment method. `null` asks the gateway for a new one.
|
|
624
|
+
*/
|
|
625
|
+
customerRef: string | null;
|
|
626
|
+
}
|
|
627
|
+
interface StartPaymentMethodSetupInput {
|
|
628
|
+
subject: PaymentMethodSetupSubject;
|
|
629
|
+
holder: PaymentMethodHolder;
|
|
630
|
+
/** What the form offers, from the account's `methods`. */
|
|
631
|
+
methods: readonly PaymentMethodType[];
|
|
632
|
+
/** Where the gateway sends the person once the form is done. */
|
|
633
|
+
successUrl: string;
|
|
634
|
+
/** Where the gateway sends the person who leaves the form. */
|
|
635
|
+
cancelUrl: string;
|
|
636
|
+
}
|
|
637
|
+
/** A body and headers exactly as they arrived, before anything parsed them. */
|
|
638
|
+
interface PaymentGatewayCallback {
|
|
639
|
+
body: string | Uint8Array;
|
|
640
|
+
headers: Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
641
|
+
}
|
|
642
|
+
interface PaymentMethodSetupSession {
|
|
643
|
+
/**
|
|
644
|
+
* The gateway's identifier of the session, unique within its account — and
|
|
645
|
+
* an adapter that has no session of its own makes one per start rather than
|
|
646
|
+
* a constant. A session is confirmed once, which the event log holds, so a
|
|
647
|
+
* value two starts share lets the second confirmation through as the
|
|
648
|
+
* duplicate it is not.
|
|
649
|
+
*/
|
|
650
|
+
sessionRef: string;
|
|
651
|
+
/** The gateway's form, where the person is sent next. */
|
|
652
|
+
redirectUrl: string;
|
|
653
|
+
/** The customer the payment method is set up for, created if none was given. */
|
|
654
|
+
customerRef: string;
|
|
655
|
+
/**
|
|
656
|
+
* A confirmation the gateway already holds when the session starts, to be
|
|
657
|
+
* handled like any callback. Only a gateway without a form of its own has
|
|
658
|
+
* one — the development gateway; a real gateway confirms through its
|
|
659
|
+
* webhook.
|
|
660
|
+
*/
|
|
661
|
+
immediateCallback?: PaymentGatewayCallback;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* What SaaSiCat keeps about a payment method: enough to show which one it is,
|
|
665
|
+
* never enough to pay with it (`SC-PRIV-005`).
|
|
666
|
+
*/
|
|
667
|
+
interface MaskedPaymentMethod {
|
|
668
|
+
type: PaymentMethodType;
|
|
669
|
+
/** The card network, such as `visa`; `null` for a direct debit. */
|
|
670
|
+
brand: string | null;
|
|
671
|
+
/** The last four digits of the card number or the IBAN. */
|
|
672
|
+
last4: string;
|
|
673
|
+
/** 1–12; `null` for a direct debit. */
|
|
674
|
+
expiryMonth: number | null;
|
|
675
|
+
/** Four digits; `null` for a direct debit. */
|
|
676
|
+
expiryYear: number | null;
|
|
677
|
+
/** ISO 3166-1 alpha-2 of the card's issuer or the bank account, where the gateway says. */
|
|
678
|
+
country: string | null;
|
|
679
|
+
/** The bank code of a direct debit account, where the gateway says. */
|
|
680
|
+
bankCode: string | null;
|
|
681
|
+
/** The reference of a direct debit mandate, which a debit announcement quotes. */
|
|
682
|
+
mandateReference: string | null;
|
|
683
|
+
}
|
|
684
|
+
/** A payment method the gateway confirmed, with the references that reach it there. */
|
|
685
|
+
interface ConfirmedPaymentMethod extends MaskedPaymentMethod {
|
|
686
|
+
customerRef: string;
|
|
687
|
+
paymentMethodRef: string;
|
|
688
|
+
}
|
|
689
|
+
/** A gateway callback, verified and translated. */
|
|
690
|
+
type PaymentGatewayEvent = {
|
|
691
|
+
kind: 'payment-method-confirmed';
|
|
692
|
+
/** The gateway's identifier of the event, unique within its account. */
|
|
693
|
+
eventId: string;
|
|
694
|
+
/** When the gateway says it happened. */
|
|
695
|
+
occurredAt: Date;
|
|
696
|
+
sessionRef: string;
|
|
697
|
+
subject: PaymentMethodSetupSubject;
|
|
698
|
+
paymentMethod: ConfirmedPaymentMethod;
|
|
699
|
+
} | {
|
|
700
|
+
kind: 'payment-method-setup-failed';
|
|
701
|
+
eventId: string;
|
|
702
|
+
occurredAt: Date;
|
|
703
|
+
sessionRef: string;
|
|
704
|
+
subject: PaymentMethodSetupSubject;
|
|
705
|
+
} | {
|
|
706
|
+
/** Genuine, and nothing SaaSiCat acts on. */
|
|
707
|
+
kind: 'unhandled';
|
|
708
|
+
eventId: string;
|
|
709
|
+
occurredAt: Date;
|
|
710
|
+
/** The gateway's own name for the event, for the log. */
|
|
711
|
+
type: string;
|
|
712
|
+
};
|
|
713
|
+
/**
|
|
714
|
+
* One account at a payment gateway: its keys, its form and its callbacks.
|
|
715
|
+
*
|
|
716
|
+
* An adapter is bound to one account, and `config/saas.yaml#payments.accounts`
|
|
717
|
+
* names it. Mollie or any other provider is another adapter behind this port.
|
|
718
|
+
*/
|
|
719
|
+
interface PaymentGateway {
|
|
720
|
+
/** The provider, as `config/saas.yaml` names it, e.g. `stripe`. */
|
|
721
|
+
readonly provider: string;
|
|
722
|
+
/**
|
|
723
|
+
* Opens the gateway's form for a payment method. Nothing is confirmed until
|
|
724
|
+
* the gateway says so through `readCallback`.
|
|
725
|
+
*/
|
|
726
|
+
startPaymentMethodSetup(input: StartPaymentMethodSetupInput): Promise<PaymentMethodSetupSession>;
|
|
727
|
+
/**
|
|
728
|
+
* Verifies a callback with the account's secret and translates it.
|
|
729
|
+
* Throws `PaymentCallbackRejectedError` for anything the gateway did not
|
|
730
|
+
* send, before a single field of it is trusted.
|
|
731
|
+
*/
|
|
732
|
+
readCallback(callback: PaymentGatewayCallback): Promise<PaymentGatewayEvent>;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* A callback that is not the gateway's: a missing or wrong signature, a stale
|
|
736
|
+
* timestamp, a body that was altered. Nothing is read from it.
|
|
737
|
+
*/
|
|
738
|
+
declare class PaymentCallbackRejectedError extends Error {
|
|
739
|
+
readonly code = "PAYMENT_CALLBACK_REJECTED";
|
|
740
|
+
constructor(reason: string);
|
|
741
|
+
}
|
|
742
|
+
/** Realm-safe type guard, like `isPlatformUserExistsError`. */
|
|
743
|
+
declare function isPaymentCallbackRejectedError(err: unknown): err is PaymentCallbackRejectedError;
|
|
744
|
+
|
|
476
745
|
type FeatureKey = string;
|
|
477
746
|
type PlanId = string;
|
|
478
747
|
type QuotaKey = string;
|
|
@@ -589,8 +858,57 @@ interface PlanCatalogNotifications {
|
|
|
589
858
|
/** Addresses mailed when a start finds the applied settings changed. */
|
|
590
859
|
settingsChanged?: string[];
|
|
591
860
|
}
|
|
592
|
-
|
|
593
|
-
|
|
861
|
+
/**
|
|
862
|
+
* The legal entity on the operator's side of every contract the installation
|
|
863
|
+
* concludes. A contract copies it on the day it is concluded; only the legal
|
|
864
|
+
* name is required while nothing is invoiced.
|
|
865
|
+
*/
|
|
866
|
+
interface PlanCatalogIssuer {
|
|
867
|
+
legalName: string;
|
|
868
|
+
addressLine1?: string;
|
|
869
|
+
addressLine2?: string;
|
|
870
|
+
postalCode?: string;
|
|
871
|
+
city?: string;
|
|
872
|
+
/** ISO 3166-1 alpha-2. */
|
|
873
|
+
country?: string;
|
|
874
|
+
vatId?: string;
|
|
875
|
+
taxNumber?: string;
|
|
876
|
+
}
|
|
877
|
+
/** How the parties contracts are concluded with are numbered. */
|
|
878
|
+
interface PlanCatalogSubscribers {
|
|
879
|
+
/**
|
|
880
|
+
* Put in front of every customer number assigned from the next start on.
|
|
881
|
+
* A number keeps the prefix it was assigned with.
|
|
882
|
+
*/
|
|
883
|
+
customerNumberPrefix?: string;
|
|
884
|
+
}
|
|
885
|
+
/** One account at a payment gateway, by the name `PlanCatalogPayments.accounts` gives it. */
|
|
886
|
+
interface PlanCatalogPaymentAccount {
|
|
887
|
+
/** The provider its bound adapter names itself as, e.g. `stripe`. */
|
|
888
|
+
provider: string;
|
|
889
|
+
/** What a new payment method may be at this account. Read for `newPaymentMethods` only. */
|
|
890
|
+
methods?: PaymentMethodType[];
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* The gateway accounts payment methods are taken through. Their keys are bound
|
|
894
|
+
* in code from the environment, never written into the file.
|
|
895
|
+
*/
|
|
896
|
+
interface PlanCatalogPayments {
|
|
897
|
+
/** The account a new payment method is taken at. Omitted, none is taken. */
|
|
898
|
+
newPaymentMethods?: string;
|
|
899
|
+
/** The origins a gateway's form may send a person back to, such as `https://app.example.com`. */
|
|
900
|
+
returnUrlOrigins: string[];
|
|
901
|
+
/** Every account taking new payment methods or holding a reference in use. */
|
|
902
|
+
accounts: Record<string, PlanCatalogPaymentAccount>;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* The part of `config/saas.yaml` that is configuration rather than catalogue.
|
|
906
|
+
*
|
|
907
|
+
* Declared apart so it can be handed on whole — a database catalogue takes its
|
|
908
|
+
* settings from the file and its plans from the database — without anybody
|
|
909
|
+
* listing the blocks again. `CATALOGUE_KEYS` names what is left over.
|
|
910
|
+
*/
|
|
911
|
+
interface PlanCatalogSettings {
|
|
594
912
|
/** App identity (branding + version), see PlanCatalogApp. */
|
|
595
913
|
app: PlanCatalogApp;
|
|
596
914
|
/** ISO-4217 currency code. */
|
|
@@ -603,6 +921,15 @@ interface PlanCatalog {
|
|
|
603
921
|
marketing?: PlanCatalogMarketing;
|
|
604
922
|
/** Who is told when the settings change between two starts. Optional. */
|
|
605
923
|
notifications?: PlanCatalogNotifications;
|
|
924
|
+
/** The operator's side of every contract. Optional until invoicing requires it. */
|
|
925
|
+
issuer?: PlanCatalogIssuer;
|
|
926
|
+
/** How subscribers are numbered. Optional. */
|
|
927
|
+
subscribers?: PlanCatalogSubscribers;
|
|
928
|
+
/** The payment gateway accounts. Optional until payment methods are taken. */
|
|
929
|
+
payments?: PlanCatalogPayments;
|
|
930
|
+
}
|
|
931
|
+
interface PlanCatalog extends PlanCatalogSettings {
|
|
932
|
+
schemaVersion: 1;
|
|
606
933
|
features?: FeatureDef[];
|
|
607
934
|
/**
|
|
608
935
|
* Optional. When omitted, plans come exclusively from the
|
|
@@ -2125,6 +2452,14 @@ interface SettingsDifference {
|
|
|
2125
2452
|
* property the schema declares lands on one side.
|
|
2126
2453
|
*/
|
|
2127
2454
|
declare const CATALOGUE_KEYS: ReadonlySet<keyof PlanCatalog>;
|
|
2455
|
+
/**
|
|
2456
|
+
* The settings of a catalogue, typed, for handing them on as a whole.
|
|
2457
|
+
*
|
|
2458
|
+
* The same selection as `settingsSubtreeOf`, which is why it is that function:
|
|
2459
|
+
* a caller that listed the blocks it passes on would drop the next one the
|
|
2460
|
+
* schema gains, and nothing would say so.
|
|
2461
|
+
*/
|
|
2462
|
+
declare function planCatalogSettingsOf(catalog: PlanCatalog): PlanCatalogSettings;
|
|
2128
2463
|
/** Everything in the catalogue that is configuration, as it was resolved. */
|
|
2129
2464
|
declare function settingsSubtreeOf(catalog: PlanCatalog): AppliedSettingsValues;
|
|
2130
2465
|
/**
|
|
@@ -2832,9 +3167,40 @@ interface SubscriptionContractPriceSnapshot {
|
|
|
2832
3167
|
vatRate: number;
|
|
2833
3168
|
totalGross: number;
|
|
2834
3169
|
}
|
|
2835
|
-
|
|
3170
|
+
/**
|
|
3171
|
+
* The subscriber as a contract copied it on the day it was concluded.
|
|
3172
|
+
*
|
|
3173
|
+
* The invoice email is not part of it: it says how the party is reached, not
|
|
3174
|
+
* who the party is, and a contract is kept for years after an address like that
|
|
3175
|
+
* stopped mattering.
|
|
3176
|
+
*/
|
|
3177
|
+
interface ContractSubscriberParty extends LegalIdentity, PartyAddress {
|
|
3178
|
+
customerNumber: string;
|
|
3179
|
+
}
|
|
3180
|
+
/** The issuer as `config/saas.yaml` named it on the day a contract was concluded. */
|
|
3181
|
+
interface ContractIssuerParty extends LegalIdentity, PartyAddress {
|
|
3182
|
+
}
|
|
3183
|
+
/** Who a contract is between, copied when it is concluded. */
|
|
3184
|
+
interface SubscriptionContractParties {
|
|
3185
|
+
subscriberId: string;
|
|
3186
|
+
subscriber: ContractSubscriberParty;
|
|
3187
|
+
/** `null` where `config/saas.yaml` named no issuer that day. */
|
|
3188
|
+
issuer: ContractIssuerParty | null;
|
|
3189
|
+
}
|
|
3190
|
+
interface SubscriptionContractRecord extends SubscriptionContractParties {
|
|
2836
3191
|
id: string;
|
|
3192
|
+
/**
|
|
3193
|
+
* The tenant the contract was concluded for, kept as a trace. The contract
|
|
3194
|
+
* belongs to its subscriber and outlives the tenant.
|
|
3195
|
+
*/
|
|
2837
3196
|
tenantId: string;
|
|
3197
|
+
/**
|
|
3198
|
+
* The parties were copied by the migration that attached contracts
|
|
3199
|
+
* concluded before subscribers existed, not on the day the contract was
|
|
3200
|
+
* concluded. Either party may have changed in between, so such a copy is
|
|
3201
|
+
* never presented as what was agreed.
|
|
3202
|
+
*/
|
|
3203
|
+
partiesMigrated: boolean;
|
|
2838
3204
|
status: SubscriptionContractStatus;
|
|
2839
3205
|
effectiveFrom: Date;
|
|
2840
3206
|
effectiveUntil: Date | null;
|
|
@@ -2851,6 +3217,11 @@ interface SubscriptionContractRecord {
|
|
|
2851
3217
|
updatedAt: Date;
|
|
2852
3218
|
}
|
|
2853
3219
|
type NewContractLineItemData = Omit<ContractLineItemRecord, 'id' | 'contractId' | 'createdAt'>;
|
|
3220
|
+
/**
|
|
3221
|
+
* A contract as a caller asks for it. The parties are not among it: the
|
|
3222
|
+
* platform copies them from the tenant's subscriber and the configuration when
|
|
3223
|
+
* the contract is written, so no caller can name a party of its own.
|
|
3224
|
+
*/
|
|
2854
3225
|
interface CreateSubscriptionContractData {
|
|
2855
3226
|
tenantId: string;
|
|
2856
3227
|
status?: SubscriptionContractStatus;
|
|
@@ -2866,6 +3237,10 @@ interface CreateSubscriptionContractData {
|
|
|
2866
3237
|
termsSnapshot?: Record<string, unknown> | null;
|
|
2867
3238
|
lineItems: NewContractLineItemData[];
|
|
2868
3239
|
}
|
|
3240
|
+
/** What a repository writes: the contract as asked for, with the parties the platform copied. */
|
|
3241
|
+
interface NewSubscriptionContractData extends CreateSubscriptionContractData {
|
|
3242
|
+
parties: SubscriptionContractParties;
|
|
3243
|
+
}
|
|
2869
3244
|
interface TerminateSubscriptionContractData {
|
|
2870
3245
|
effectiveUntil: Date;
|
|
2871
3246
|
/**
|
|
@@ -3085,8 +3460,11 @@ interface SubscriptionContractRepository {
|
|
|
3085
3460
|
* instead of drawing an extra pool connection (starvation guard, #70).
|
|
3086
3461
|
*/
|
|
3087
3462
|
findActiveByTenantId(tenantId: string, asOf?: Date, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3088
|
-
/**
|
|
3089
|
-
|
|
3463
|
+
/**
|
|
3464
|
+
* Writes the contract with the parties it names. With `tx`, the contract is
|
|
3465
|
+
* written on that transaction and undone with it.
|
|
3466
|
+
*/
|
|
3467
|
+
create(data: NewSubscriptionContractData, tx?: TransactionContext): Promise<SubscriptionContractRecord>;
|
|
3090
3468
|
/**
|
|
3091
3469
|
* The contract concluded from a checkout offer (`originalOfferId`), or
|
|
3092
3470
|
* `null` when none was. An offer is consumed once and so yields one
|
|
@@ -3096,6 +3474,39 @@ interface SubscriptionContractRepository {
|
|
|
3096
3474
|
findByOriginalOfferId(offerId: string, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3097
3475
|
terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
|
|
3098
3476
|
}
|
|
3477
|
+
/**
|
|
3478
|
+
* The parties contracts are concluded with, their link to the tenant they are
|
|
3479
|
+
* live for, and the corrections of their legal identity.
|
|
3480
|
+
*
|
|
3481
|
+
* A subscriber has at most one live tenant and a tenant at most one live
|
|
3482
|
+
* subscriber; the database holds both, so two callers creating one for the
|
|
3483
|
+
* same tenant at once end with one.
|
|
3484
|
+
*/
|
|
3485
|
+
interface SubscriberRepository {
|
|
3486
|
+
/**
|
|
3487
|
+
* Creates a subscriber, assigns its customer number, and makes it the
|
|
3488
|
+
* tenant's live subscriber — all or nothing. `null` when the tenant already
|
|
3489
|
+
* has a live subscriber, in which case nothing is written and the caller's
|
|
3490
|
+
* transaction stays usable.
|
|
3491
|
+
*/
|
|
3492
|
+
createForTenant(data: CreateSubscriberData, tx?: TransactionContext): Promise<SubscriberRecord | null>;
|
|
3493
|
+
findById(subscriberId: string, tx?: TransactionContext): Promise<SubscriberRecord | null>;
|
|
3494
|
+
/** The subscriber live for this tenant, or `null` when it has none. */
|
|
3495
|
+
findByTenantId(tenantId: string, tx?: TransactionContext): Promise<SubscriberRecord | null>;
|
|
3496
|
+
/** Writes the members given and keeps the rest; `null` when no such subscriber exists. */
|
|
3497
|
+
updateContact(subscriberId: string, change: SubscriberContactChange, tx?: TransactionContext): Promise<SubscriberRecord | null>;
|
|
3498
|
+
/**
|
|
3499
|
+
* Writes a correction of the legal identity and records it, in one step:
|
|
3500
|
+
* the subscriber is read and changed under a lock, so the values recorded
|
|
3501
|
+
* as replaced are the ones this write replaced even when two corrections
|
|
3502
|
+
* arrive at once. A field whose stored value already equals the corrected
|
|
3503
|
+
* one is left out of the record, and when none differs nothing is written
|
|
3504
|
+
* and `correction` is `null`. `null` when no such subscriber exists.
|
|
3505
|
+
*/
|
|
3506
|
+
correctIdentity(subscriberId: string, data: SubscriberCorrectionData, tx?: TransactionContext): Promise<SubscriberCorrectionResult | null>;
|
|
3507
|
+
/** Every correction of this subscriber, the latest first. */
|
|
3508
|
+
listCorrections(subscriberId: string): Promise<SubscriberCorrectionRecord[]>;
|
|
3509
|
+
}
|
|
3099
3510
|
/**
|
|
3100
3511
|
* Display form of a subscription for the tenant self-service UI.
|
|
3101
3512
|
* Richer than `SubscriptionRecord` (which is only the aggregation form); contains
|
|
@@ -4053,6 +4464,160 @@ interface CheckoutOfferRepository {
|
|
|
4053
4464
|
consume(id: string, tx?: TransactionContext): Promise<CheckoutOfferRow>;
|
|
4054
4465
|
}
|
|
4055
4466
|
|
|
4467
|
+
/** `ACTIVE` is the one in use; `REPLACED` is one a later payment method took over from. */
|
|
4468
|
+
type SubscriberPaymentMethodStatus = 'ACTIVE' | 'REPLACED';
|
|
4469
|
+
interface SubscriberPaymentMethodRecord extends ConfirmedPaymentMethod {
|
|
4470
|
+
id: string;
|
|
4471
|
+
subscriberId: string;
|
|
4472
|
+
/** The account in `config/saas.yaml#payments.accounts` the references belong to. */
|
|
4473
|
+
gatewayAccount: string;
|
|
4474
|
+
/** The provider of that account when the payment method was confirmed. */
|
|
4475
|
+
provider: string;
|
|
4476
|
+
status: SubscriberPaymentMethodStatus;
|
|
4477
|
+
/** When the gateway confirmed the payment method. */
|
|
4478
|
+
confirmedAt: Date;
|
|
4479
|
+
/** When a later payment method took over; `null` while this one is in use. */
|
|
4480
|
+
replacedAt: Date | null;
|
|
4481
|
+
createdAt: Date;
|
|
4482
|
+
}
|
|
4483
|
+
/** What a repository records for a payment method the gateway confirmed. */
|
|
4484
|
+
interface RecordSubscriberPaymentMethodData extends ConfirmedPaymentMethod {
|
|
4485
|
+
subscriberId: string;
|
|
4486
|
+
gatewayAccount: string;
|
|
4487
|
+
provider: string;
|
|
4488
|
+
confirmedAt: Date;
|
|
4489
|
+
}
|
|
4490
|
+
/**
|
|
4491
|
+
* - `activated`: it is the subscriber's payment method now, and the one it
|
|
4492
|
+
* replaced, if any, is `REPLACED`.
|
|
4493
|
+
* - `already-recorded`: the account's reference was recorded before; nothing
|
|
4494
|
+
* was written, and `method` is the row that holds it.
|
|
4495
|
+
* - `superseded`: the subscriber's payment method in use was confirmed after
|
|
4496
|
+
* this one, so this one is recorded as already replaced — confirmations can
|
|
4497
|
+
* arrive in another order than the forms were filled in.
|
|
4498
|
+
*/
|
|
4499
|
+
type RecordSubscriberPaymentMethodOutcome = 'activated' | 'already-recorded' | 'superseded';
|
|
4500
|
+
/**
|
|
4501
|
+
* A change of payment method a tenant started: the gateway session it opened
|
|
4502
|
+
* for the subscriber. A confirmation is recorded only against the setup it
|
|
4503
|
+
* belongs to, so a callback that names another subscriber than the session was
|
|
4504
|
+
* opened for changes nobody's payment method.
|
|
4505
|
+
*/
|
|
4506
|
+
interface SubscriberPaymentMethodSetupData {
|
|
4507
|
+
subscriberId: string;
|
|
4508
|
+
gatewayAccount: string;
|
|
4509
|
+
/** The gateway's session, unique within the account. */
|
|
4510
|
+
sessionRef: string;
|
|
4511
|
+
/** The customer the gateway keeps the payment method under. */
|
|
4512
|
+
customerRef: string;
|
|
4513
|
+
startedAt: Date;
|
|
4514
|
+
}
|
|
4515
|
+
/** Which setup a confirmation claims to complete. */
|
|
4516
|
+
interface SubscriberPaymentMethodSetupMatch {
|
|
4517
|
+
gatewayAccount: string;
|
|
4518
|
+
sessionRef: string;
|
|
4519
|
+
subscriberId: string;
|
|
4520
|
+
}
|
|
4521
|
+
interface RecordSubscriberPaymentMethodResult {
|
|
4522
|
+
method: SubscriberPaymentMethodRecord;
|
|
4523
|
+
outcome: RecordSubscriberPaymentMethodOutcome;
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
/** A gateway event, as the log records it. */
|
|
4527
|
+
interface PaymentEventClaim {
|
|
4528
|
+
/** The account the event came from; an event identifier is unique only within it. */
|
|
4529
|
+
gatewayAccount: string;
|
|
4530
|
+
eventId: string;
|
|
4531
|
+
provider: string;
|
|
4532
|
+
/** The gateway session the event is about, where it is about one. */
|
|
4533
|
+
sessionId: string | null;
|
|
4534
|
+
kind: PaymentGatewayEvent['kind'];
|
|
4535
|
+
/** What the event said, without anything that names or reaches a person. */
|
|
4536
|
+
summary: Record<string, unknown>;
|
|
4537
|
+
}
|
|
4538
|
+
/**
|
|
4539
|
+
* The events a gateway sent, each handled once.
|
|
4540
|
+
*
|
|
4541
|
+
* Gateways deliver at least once, so the same event arrives again after a
|
|
4542
|
+
* timeout or a retry. An event is claimed on the transaction that writes what
|
|
4543
|
+
* it changes: when that transaction rolls back, the claim goes with it and the
|
|
4544
|
+
* gateway's retry is handled rather than discarded as a duplicate.
|
|
4545
|
+
*/
|
|
4546
|
+
interface PaymentEventLog {
|
|
4547
|
+
/**
|
|
4548
|
+
* Records the event and returns `true`, or returns `false` when this account
|
|
4549
|
+
* already recorded it, writing nothing.
|
|
4550
|
+
*
|
|
4551
|
+
* The duplicate must not raise: on PostgreSQL an error aborts the
|
|
4552
|
+
* transaction it happened on, and the caller's transaction has to stay
|
|
4553
|
+
* usable. An `INSERT … ON CONFLICT DO NOTHING` does both — and when another
|
|
4554
|
+
* transaction holds the same claim uncommitted, it waits for that one and
|
|
4555
|
+
* answers by its outcome.
|
|
4556
|
+
*
|
|
4557
|
+
* A confirmation of a session this account already confirmed is a duplicate
|
|
4558
|
+
* as well, whatever its `eventId`: one session is set up once, and a gateway
|
|
4559
|
+
* may report it through more than one event. `sql/constraints.postgres.sql`
|
|
4560
|
+
* holds that as a second unique index, and the untargeted `DO NOTHING`
|
|
4561
|
+
* answers for it too.
|
|
4562
|
+
*/
|
|
4563
|
+
claim(claim: PaymentEventClaim, tx: TransactionContext): Promise<boolean>;
|
|
4564
|
+
/**
|
|
4565
|
+
* Takes the session off a claim whose event changed nothing, so the next
|
|
4566
|
+
* event about that session is handled instead of taken for the duplicate it
|
|
4567
|
+
* is not. The claim itself stays: that one event is never handled twice.
|
|
4568
|
+
*
|
|
4569
|
+
* The session is held from the claim onwards, which is what keeps two
|
|
4570
|
+
* confirmations delivered at once from both taking effect; an event that
|
|
4571
|
+
* turned out to have nothing to do gives it back on the same transaction.
|
|
4572
|
+
*/
|
|
4573
|
+
releaseSession(gatewayAccount: string, eventId: string, tx: TransactionContext): Promise<void>;
|
|
4574
|
+
}
|
|
4575
|
+
/**
|
|
4576
|
+
* The payment methods of subscribers, as references at the gateway accounts
|
|
4577
|
+
* that confirmed them.
|
|
4578
|
+
*
|
|
4579
|
+
* A subscriber has at most one `ACTIVE` payment method; the database holds
|
|
4580
|
+
* that, so two confirmations recorded at once for one subscriber end with one.
|
|
4581
|
+
*/
|
|
4582
|
+
interface SubscriberPaymentMethodRepository {
|
|
4583
|
+
/**
|
|
4584
|
+
* Records a confirmed payment method for its subscriber, under a lock on the
|
|
4585
|
+
* subscriber so two confirmations take turns. See
|
|
4586
|
+
* `RecordSubscriberPaymentMethodOutcome` for the three outcomes.
|
|
4587
|
+
*/
|
|
4588
|
+
recordConfirmed(data: RecordSubscriberPaymentMethodData, tx?: TransactionContext): Promise<RecordSubscriberPaymentMethodResult>;
|
|
4589
|
+
/** The subscriber's payment method in use, or `null` when it has none. */
|
|
4590
|
+
findActive(subscriberId: string, tx?: TransactionContext): Promise<SubscriberPaymentMethodRecord | null>;
|
|
4591
|
+
/**
|
|
4592
|
+
* The payment method an account's reference names, whatever its status.
|
|
4593
|
+
*
|
|
4594
|
+
* The one read that reaches a payment method a newer one replaced, which is
|
|
4595
|
+
* how `@saasicat/persistence-testing` verifies that an implementation keeps
|
|
4596
|
+
* the history rather than overwriting the row (`SC-PRIC-030`).
|
|
4597
|
+
*/
|
|
4598
|
+
findByReference(gatewayAccount: string, paymentMethodRef: string, tx?: TransactionContext): Promise<SubscriberPaymentMethodRecord | null>;
|
|
4599
|
+
/** Every account that holds a payment method in use, each once. */
|
|
4600
|
+
accountsInUse(): Promise<string[]>;
|
|
4601
|
+
/**
|
|
4602
|
+
* Records a change of payment method a tenant started, open until its
|
|
4603
|
+
* confirmation completes it.
|
|
4604
|
+
*
|
|
4605
|
+
* One session is one setup: the account and the session are unique together,
|
|
4606
|
+
* and a second setup for a session already recorded raises. A gateway hands
|
|
4607
|
+
* out a session per start, so an adapter that returns one twice is the
|
|
4608
|
+
* defect this refuses to write over.
|
|
4609
|
+
*/
|
|
4610
|
+
recordSetup(data: SubscriberPaymentMethodSetupData, tx?: TransactionContext): Promise<void>;
|
|
4611
|
+
/**
|
|
4612
|
+
* Completes the open setup the account, the session and the subscriber all
|
|
4613
|
+
* name, and returns `true` — or returns `false`, writing nothing, when no
|
|
4614
|
+
* open setup matches all three: none was started, it was started for another
|
|
4615
|
+
* subscriber, or it is complete already. A single conditional write, so two
|
|
4616
|
+
* confirmations for one setup complete it once.
|
|
4617
|
+
*/
|
|
4618
|
+
completeSetup(match: SubscriberPaymentMethodSetupMatch, completedAt: Date, tx?: TransactionContext): Promise<boolean>;
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4056
4621
|
/** Which changes to list. */
|
|
4057
4622
|
interface SettingsChangeFilter {
|
|
4058
4623
|
/** Only changes an operator has, or has not, acknowledged. Omitted: both. */
|
|
@@ -4178,6 +4743,8 @@ interface SaaSiCatPersistenceEntitlement {
|
|
|
4178
4743
|
subscriptionRepository: PersistenceProvider<SubscriptionRepository>;
|
|
4179
4744
|
planVersionRepository: PersistenceProvider<PlanVersionRepository>;
|
|
4180
4745
|
subscriptionContractRepository?: PersistenceProvider<SubscriptionContractRepository>;
|
|
4746
|
+
/** The parties contracts are concluded with; required wherever contracts are written. */
|
|
4747
|
+
subscriberRepository?: PersistenceProvider<SubscriberRepository>;
|
|
4181
4748
|
subscriptionBundleRepository?: PersistenceProvider<SubscriptionBundleRepository>;
|
|
4182
4749
|
bundleRepository?: PersistenceProvider<BundleRepository>;
|
|
4183
4750
|
}
|
|
@@ -4204,6 +4771,15 @@ interface SaaSiCatPersistenceTenantBilling {
|
|
|
4204
4771
|
subscriptionWritePort: PersistenceProvider<TenantSubscriptionWritePort>;
|
|
4205
4772
|
usageSnapshotPort?: PersistenceProvider<UsageSnapshotPort>;
|
|
4206
4773
|
}
|
|
4774
|
+
/**
|
|
4775
|
+
* The record of payment gateway callbacks and the payment methods they confirm
|
|
4776
|
+
* (`payments` in `SaaSiCatModule.forRoot`). Both are written on the transaction
|
|
4777
|
+
* a callback is handled on, so they come from the adapter that runs it.
|
|
4778
|
+
*/
|
|
4779
|
+
interface SaaSiCatPersistencePayments {
|
|
4780
|
+
paymentEventLog: PersistenceProvider<PaymentEventLog>;
|
|
4781
|
+
subscriberPaymentMethodRepository: PersistenceProvider<SubscriberPaymentMethodRepository>;
|
|
4782
|
+
}
|
|
4207
4783
|
/** Read/write backing for the standard SuperAdmin resource pages. */
|
|
4208
4784
|
interface SaaSiCatPersistenceAdminResources {
|
|
4209
4785
|
resources: PersistenceProvider<AdminResourcesPort>;
|
|
@@ -4238,6 +4814,8 @@ interface SaaSiCatPersistenceAdapter {
|
|
|
4238
4814
|
/** Tenant, user, audit and subscription resources for the SuperAdmin UI. */
|
|
4239
4815
|
adminResources?: SaaSiCatPersistenceAdminResources;
|
|
4240
4816
|
promo?: SaaSiCatPersistencePromo;
|
|
4817
|
+
/** Payment gateway callbacks and subscriber payment methods. */
|
|
4818
|
+
payments?: SaaSiCatPersistencePayments;
|
|
4241
4819
|
/** DB hydration of the plan catalog at boot (`PlanCatalogModule`). */
|
|
4242
4820
|
planCatalogReadSink?: PersistenceProvider<PlanCatalogReadSink>;
|
|
4243
4821
|
/** One-shot `saas.yaml → DB` import. */
|
|
@@ -4491,6 +5069,32 @@ declare const CONTRACT_ERROR_CODES: {
|
|
|
4491
5069
|
readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
|
|
4492
5070
|
};
|
|
4493
5071
|
type ContractErrorCode = (typeof CONTRACT_ERROR_CODES)[keyof typeof CONTRACT_ERROR_CODES];
|
|
5072
|
+
/** The parties contracts are concluded with (`SubscriberService`), and their absence. */
|
|
5073
|
+
declare const SUBSCRIBER_ERROR_CODES: {
|
|
5074
|
+
/**
|
|
5075
|
+
* A contract, a plan change or a booking for a tenant that has no
|
|
5076
|
+
* subscriber. Nothing is agreed or charged without the party to it.
|
|
5077
|
+
* Carries `tenantId`.
|
|
5078
|
+
*/
|
|
5079
|
+
readonly SUBSCRIBER_REQUIRED: "SUBSCRIBER_REQUIRED";
|
|
5080
|
+
/** The tenant already has a live subscriber. Carries `tenantId`. */
|
|
5081
|
+
readonly SUBSCRIBER_ALREADY_EXISTS: "SUBSCRIBER_ALREADY_EXISTS";
|
|
5082
|
+
readonly SUBSCRIBER_NOT_FOUND: "SUBSCRIBER_NOT_FOUND";
|
|
5083
|
+
readonly SUBSCRIBER_LEGAL_NAME_REQUIRED: "SUBSCRIBER_LEGAL_NAME_REQUIRED";
|
|
5084
|
+
/**
|
|
5085
|
+
* A detail that has a form — the country, the invoice email — is not in it,
|
|
5086
|
+
* or one sign-up requires — the billing address — is missing. Carries `field`.
|
|
5087
|
+
*/
|
|
5088
|
+
readonly SUBSCRIBER_DETAIL_INVALID: "SUBSCRIBER_DETAIL_INVALID";
|
|
5089
|
+
/** A contact change named a field of the legal identity. Carries `field`. */
|
|
5090
|
+
readonly SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "SUBSCRIBER_IDENTITY_NOT_A_CONTACT";
|
|
5091
|
+
readonly SUBSCRIBER_CORRECTION_REASON_REQUIRED: "SUBSCRIBER_CORRECTION_REASON_REQUIRED";
|
|
5092
|
+
readonly SUBSCRIBER_CORRECTION_ACTOR_REQUIRED: "SUBSCRIBER_CORRECTION_ACTOR_REQUIRED";
|
|
5093
|
+
readonly SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "SUBSCRIBER_CORRECTION_CHANGES_NOTHING";
|
|
5094
|
+
/** The operator declared another legal entity: that is a transfer, not an edit. */
|
|
5095
|
+
readonly SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER";
|
|
5096
|
+
};
|
|
5097
|
+
type SubscriberErrorCode = (typeof SUBSCRIBER_ERROR_CODES)[keyof typeof SUBSCRIBER_ERROR_CODES];
|
|
4494
5098
|
/** Self-service registration funnel (`PendingRegistration`). */
|
|
4495
5099
|
declare const REGISTRATION_ERROR_CODES: {
|
|
4496
5100
|
readonly PENDING_REGISTRATION_NOT_FOUND: "PENDING_REGISTRATION_NOT_FOUND";
|
|
@@ -4519,6 +5123,12 @@ declare const AUTH_ERROR_CODES: {
|
|
|
4519
5123
|
/** Neither `tenantId` nor `userId` could be resolved from the request. */
|
|
4520
5124
|
readonly TENANT_CONTEXT_MISSING: "TENANT_CONTEXT_MISSING";
|
|
4521
5125
|
readonly TENANT_ADMIN_REQUIRED: "TENANT_ADMIN_REQUIRED";
|
|
5126
|
+
/**
|
|
5127
|
+
* The tenant's billing area — its payment method, and later its invoices
|
|
5128
|
+
* and account — needs the billing permission, which the application maps
|
|
5129
|
+
* to its roles and the tenant's administrator holds by default.
|
|
5130
|
+
*/
|
|
5131
|
+
readonly BILLING_PERMISSION_REQUIRED: "BILLING_PERMISSION_REQUIRED";
|
|
4522
5132
|
readonly SUPER_ADMIN_REQUIRED: "SUPER_ADMIN_REQUIRED";
|
|
4523
5133
|
/** TOTP MFA has never been set up for this user. */
|
|
4524
5134
|
readonly MFA_NOT_SET_UP: "MFA_NOT_SET_UP";
|
|
@@ -4549,6 +5159,24 @@ declare const PROMO_ERROR_CODES: {
|
|
|
4549
5159
|
readonly PROMO_MAX_REDEMPTIONS_LOWERED: "PROMO_MAX_REDEMPTIONS_LOWERED";
|
|
4550
5160
|
};
|
|
4551
5161
|
type PromoErrorCode = (typeof PROMO_ERROR_CODES)[keyof typeof PROMO_ERROR_CODES];
|
|
5162
|
+
/** Payment methods and the gateways that confirm them. */
|
|
5163
|
+
declare const PAYMENT_ERROR_CODES: {
|
|
5164
|
+
/**
|
|
5165
|
+
* No gateway account takes new payment methods:
|
|
5166
|
+
* `config/saas.yaml#payments.newPaymentMethods` names none.
|
|
5167
|
+
*/
|
|
5168
|
+
readonly PAYMENTS_NOT_CONFIGURED: "PAYMENTS_NOT_CONFIGURED";
|
|
5169
|
+
/** A callback arrived for an account `config/saas.yaml#payments.accounts` does not name. Carries `account`. */
|
|
5170
|
+
readonly PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "PAYMENT_GATEWAY_ACCOUNT_UNKNOWN";
|
|
5171
|
+
/** A callback the gateway did not send: its signature does not verify. */
|
|
5172
|
+
readonly PAYMENT_CALLBACK_REJECTED: "PAYMENT_CALLBACK_REJECTED";
|
|
5173
|
+
/**
|
|
5174
|
+
* A success or cancel URL at an origin `config/saas.yaml#payments.returnUrlOrigins`
|
|
5175
|
+
* does not name. Carries `field`.
|
|
5176
|
+
*/
|
|
5177
|
+
readonly PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED";
|
|
5178
|
+
};
|
|
5179
|
+
type PaymentErrorCode = (typeof PAYMENT_ERROR_CODES)[keyof typeof PAYMENT_ERROR_CODES];
|
|
4552
5180
|
/** Codes of the settings record (`GET /admin/settings`, the acknowledgement). */
|
|
4553
5181
|
declare const SETTINGS_ERROR_CODES: {
|
|
4554
5182
|
/** No recorded change has this id, or the installation keeps no record at all. */
|
|
@@ -4565,6 +5193,20 @@ type SettingsErrorCode = (typeof SETTINGS_ERROR_CODES)[keyof typeof SETTINGS_ERR
|
|
|
4565
5193
|
declare const PLATFORM_ERROR_CODES: {
|
|
4566
5194
|
/** No recorded change has this id, or the installation keeps no record at all. */
|
|
4567
5195
|
readonly SETTINGS_CHANGE_NOT_FOUND: "SETTINGS_CHANGE_NOT_FOUND";
|
|
5196
|
+
/**
|
|
5197
|
+
* No gateway account takes new payment methods:
|
|
5198
|
+
* `config/saas.yaml#payments.newPaymentMethods` names none.
|
|
5199
|
+
*/
|
|
5200
|
+
readonly PAYMENTS_NOT_CONFIGURED: "PAYMENTS_NOT_CONFIGURED";
|
|
5201
|
+
/** A callback arrived for an account `config/saas.yaml#payments.accounts` does not name. Carries `account`. */
|
|
5202
|
+
readonly PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "PAYMENT_GATEWAY_ACCOUNT_UNKNOWN";
|
|
5203
|
+
/** A callback the gateway did not send: its signature does not verify. */
|
|
5204
|
+
readonly PAYMENT_CALLBACK_REJECTED: "PAYMENT_CALLBACK_REJECTED";
|
|
5205
|
+
/**
|
|
5206
|
+
* A success or cancel URL at an origin `config/saas.yaml#payments.returnUrlOrigins`
|
|
5207
|
+
* does not name. Carries `field`.
|
|
5208
|
+
*/
|
|
5209
|
+
readonly PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED";
|
|
4568
5210
|
readonly PENDING_REGISTRATION_NOT_FOUND: "PENDING_REGISTRATION_NOT_FOUND";
|
|
4569
5211
|
readonly PENDING_REGISTRATION_EXPIRED: "PENDING_REGISTRATION_EXPIRED";
|
|
4570
5212
|
readonly INVALID_REGISTRATION_STATE: "INVALID_REGISTRATION_STATE";
|
|
@@ -4580,6 +5222,28 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4580
5222
|
readonly PLAN_NOT_AVAILABLE: "PLAN_NOT_AVAILABLE";
|
|
4581
5223
|
readonly PLAN_NOT_SELECTED: "PLAN_NOT_SELECTED";
|
|
4582
5224
|
readonly MODEL_NOT_AVAILABLE: "MODEL_NOT_AVAILABLE";
|
|
5225
|
+
/**
|
|
5226
|
+
* A contract, a plan change or a booking for a tenant that has no
|
|
5227
|
+
* subscriber. Nothing is agreed or charged without the party to it.
|
|
5228
|
+
* Carries `tenantId`.
|
|
5229
|
+
*/
|
|
5230
|
+
readonly SUBSCRIBER_REQUIRED: "SUBSCRIBER_REQUIRED";
|
|
5231
|
+
/** The tenant already has a live subscriber. Carries `tenantId`. */
|
|
5232
|
+
readonly SUBSCRIBER_ALREADY_EXISTS: "SUBSCRIBER_ALREADY_EXISTS";
|
|
5233
|
+
readonly SUBSCRIBER_NOT_FOUND: "SUBSCRIBER_NOT_FOUND";
|
|
5234
|
+
readonly SUBSCRIBER_LEGAL_NAME_REQUIRED: "SUBSCRIBER_LEGAL_NAME_REQUIRED";
|
|
5235
|
+
/**
|
|
5236
|
+
* A detail that has a form — the country, the invoice email — is not in it,
|
|
5237
|
+
* or one sign-up requires — the billing address — is missing. Carries `field`.
|
|
5238
|
+
*/
|
|
5239
|
+
readonly SUBSCRIBER_DETAIL_INVALID: "SUBSCRIBER_DETAIL_INVALID";
|
|
5240
|
+
/** A contact change named a field of the legal identity. Carries `field`. */
|
|
5241
|
+
readonly SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "SUBSCRIBER_IDENTITY_NOT_A_CONTACT";
|
|
5242
|
+
readonly SUBSCRIBER_CORRECTION_REASON_REQUIRED: "SUBSCRIBER_CORRECTION_REASON_REQUIRED";
|
|
5243
|
+
readonly SUBSCRIBER_CORRECTION_ACTOR_REQUIRED: "SUBSCRIBER_CORRECTION_ACTOR_REQUIRED";
|
|
5244
|
+
readonly SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "SUBSCRIBER_CORRECTION_CHANGES_NOTHING";
|
|
5245
|
+
/** The operator declared another legal entity: that is a transfer, not an edit. */
|
|
5246
|
+
readonly SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER";
|
|
4583
5247
|
readonly CHECKOUT_OFFER_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_LINE_ITEMS_REQUIRED";
|
|
4584
5248
|
readonly CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED: "CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED";
|
|
4585
5249
|
readonly CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED";
|
|
@@ -4800,6 +5464,12 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4800
5464
|
/** Neither `tenantId` nor `userId` could be resolved from the request. */
|
|
4801
5465
|
readonly TENANT_CONTEXT_MISSING: "TENANT_CONTEXT_MISSING";
|
|
4802
5466
|
readonly TENANT_ADMIN_REQUIRED: "TENANT_ADMIN_REQUIRED";
|
|
5467
|
+
/**
|
|
5468
|
+
* The tenant's billing area — its payment method, and later its invoices
|
|
5469
|
+
* and account — needs the billing permission, which the application maps
|
|
5470
|
+
* to its roles and the tenant's administrator holds by default.
|
|
5471
|
+
*/
|
|
5472
|
+
readonly BILLING_PERMISSION_REQUIRED: "BILLING_PERMISSION_REQUIRED";
|
|
4803
5473
|
readonly SUPER_ADMIN_REQUIRED: "SUPER_ADMIN_REQUIRED";
|
|
4804
5474
|
/** TOTP MFA has never been set up for this user. */
|
|
4805
5475
|
readonly MFA_NOT_SET_UP: "MFA_NOT_SET_UP";
|
|
@@ -4820,7 +5490,7 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4820
5490
|
/** Email already taken (mapped from `PlatformUserExistsError`). */
|
|
4821
5491
|
readonly EMAIL_EXISTS: "EMAIL_EXISTS";
|
|
4822
5492
|
};
|
|
4823
|
-
type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | RegistrationErrorCode | SettingsErrorCode;
|
|
5493
|
+
type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | SubscriberErrorCode | RegistrationErrorCode | PaymentErrorCode | SettingsErrorCode;
|
|
4824
5494
|
/**
|
|
4825
5495
|
* Shape of a coded error response.
|
|
4826
5496
|
*
|
|
@@ -5041,7 +5711,25 @@ interface PendingRegistration {
|
|
|
5041
5711
|
billingCycle: 'MONTHLY' | 'YEARLY' | null;
|
|
5042
5712
|
/** Plaintext code (UI display). Validation runs fresh every time. */
|
|
5043
5713
|
appliedPromoCode: string | null;
|
|
5714
|
+
/**
|
|
5715
|
+
* The billing address and tax identifiers step 4 asks for, which the
|
|
5716
|
+
* subscriber is created with. The address is required before a payment
|
|
5717
|
+
* method is set up; the tax identifiers stay optional.
|
|
5718
|
+
*/
|
|
5719
|
+
addressLine1: string | null;
|
|
5720
|
+
addressLine2: string | null;
|
|
5721
|
+
postalCode: string | null;
|
|
5722
|
+
city: string | null;
|
|
5723
|
+
/** ISO 3166-1 alpha-2, upper case. */
|
|
5724
|
+
country: string | null;
|
|
5725
|
+
vatId: string | null;
|
|
5726
|
+
taxNumber: string | null;
|
|
5727
|
+
/** The gateway's session for the payment method, unique within `checkoutGatewayAccount`. */
|
|
5044
5728
|
checkoutSessionId: string | null;
|
|
5729
|
+
/** The account in `config/saas.yaml#payments.accounts` the session was opened at. */
|
|
5730
|
+
checkoutGatewayAccount: string | null;
|
|
5731
|
+
/** The customer the gateway created for the sign-up, reused when step 4 is repeated. */
|
|
5732
|
+
gatewayCustomerRef: string | null;
|
|
5045
5733
|
checkoutStartedAt: Date | null;
|
|
5046
5734
|
expiresAt: Date;
|
|
5047
5735
|
createdAt: Date;
|
|
@@ -5073,7 +5761,16 @@ interface PendingRegistrationUpdateInput {
|
|
|
5073
5761
|
configJson?: RegistrationConfigSelection | null;
|
|
5074
5762
|
billingCycle?: 'MONTHLY' | 'YEARLY' | null;
|
|
5075
5763
|
appliedPromoCode?: string | null;
|
|
5764
|
+
addressLine1?: string | null;
|
|
5765
|
+
addressLine2?: string | null;
|
|
5766
|
+
postalCode?: string | null;
|
|
5767
|
+
city?: string | null;
|
|
5768
|
+
country?: string | null;
|
|
5769
|
+
vatId?: string | null;
|
|
5770
|
+
taxNumber?: string | null;
|
|
5076
5771
|
checkoutSessionId?: string | null;
|
|
5772
|
+
checkoutGatewayAccount?: string | null;
|
|
5773
|
+
gatewayCustomerRef?: string | null;
|
|
5077
5774
|
checkoutStartedAt?: Date | null;
|
|
5078
5775
|
expiresAt?: Date;
|
|
5079
5776
|
}
|
|
@@ -5081,14 +5778,24 @@ interface PendingRegistrationUpdateInput {
|
|
|
5081
5778
|
interface PendingRegistrationRepository {
|
|
5082
5779
|
findById(id: string): Promise<PendingRegistration | null>;
|
|
5083
5780
|
findByEmail(email: string): Promise<PendingRegistration | null>;
|
|
5084
|
-
/**
|
|
5085
|
-
|
|
5781
|
+
/**
|
|
5782
|
+
* Finds the pending record a gateway session belongs to. A session
|
|
5783
|
+
* identifier is unique only within its account, so both are matched.
|
|
5784
|
+
*/
|
|
5785
|
+
findByCheckoutSession(gatewayAccount: string, sessionId: string): Promise<PendingRegistration | null>;
|
|
5086
5786
|
/**
|
|
5087
5787
|
* Cleanup lookup: all pending records with `expiresAt < now`, max
|
|
5088
5788
|
* `limit` entries per call (batch protection). Ordering irrelevant, the
|
|
5089
5789
|
* cron service iterates sequentially.
|
|
5090
5790
|
*/
|
|
5091
5791
|
findExpired(now: Date, limit: number): Promise<PendingRegistration[]>;
|
|
5792
|
+
/**
|
|
5793
|
+
* Every gateway account a checkout session is still open at: the distinct
|
|
5794
|
+
* `checkoutGatewayAccount` of records in `CHECKOUT_STARTED` whose
|
|
5795
|
+
* `expiresAt` is after `now`. The start refuses when one of them is no
|
|
5796
|
+
* longer configured, because that sign-up's confirmation could not arrive.
|
|
5797
|
+
*/
|
|
5798
|
+
findOpenCheckoutAccounts(now: Date): Promise<string[]>;
|
|
5092
5799
|
create(input: PendingRegistrationCreateInput): Promise<PendingRegistration>;
|
|
5093
5800
|
update(id: string, input: PendingRegistrationUpdateInput): Promise<PendingRegistration>;
|
|
5094
5801
|
/**
|
|
@@ -5098,7 +5805,13 @@ interface PendingRegistrationRepository {
|
|
|
5098
5805
|
* value is the authoritative threshold for the lockout check.
|
|
5099
5806
|
*/
|
|
5100
5807
|
incrementOtpAttemptCount(id: string): Promise<number>;
|
|
5101
|
-
|
|
5808
|
+
/**
|
|
5809
|
+
* Removes the record. With `tx` it is removed on that transaction and comes
|
|
5810
|
+
* back with its rollback — an activation deletes the sign-up on the
|
|
5811
|
+
* transaction that creates the tenant, so a sign-up is either still waiting
|
|
5812
|
+
* or activated, never both.
|
|
5813
|
+
*/
|
|
5814
|
+
delete(id: string, tx?: TransactionContext): Promise<void>;
|
|
5102
5815
|
}
|
|
5103
5816
|
/** Adapter port: detects whether a full user account (verified) exists for this email. */
|
|
5104
5817
|
interface UserAccountLookup {
|
|
@@ -5108,67 +5821,42 @@ interface UserAccountLookup {
|
|
|
5108
5821
|
interface SlugAvailabilityCheck {
|
|
5109
5822
|
isSlugAvailable(slug: string): Promise<boolean>;
|
|
5110
5823
|
}
|
|
5111
|
-
/** Wire format of a created checkout session (provider-agnostic). */
|
|
5112
|
-
interface CheckoutSession {
|
|
5113
|
-
/** Provider-specific session ID (e.g. Stripe `cs_…`). */
|
|
5114
|
-
sessionId: string;
|
|
5115
|
-
/** Payment URL to be opened by the frontend. */
|
|
5116
|
-
checkoutUrl: string;
|
|
5117
|
-
/** Optional: provider name (`stripe`, `dev-stub`) for logging/audit. */
|
|
5118
|
-
provider?: string;
|
|
5119
|
-
}
|
|
5120
|
-
type PaymentEventStatus = 'SUCCEEDED' | 'FAILED';
|
|
5121
|
-
/**
|
|
5122
|
-
* Adapter port: idempotency log for payment webhooks. Stripe (and most
|
|
5123
|
-
* other providers) deliver events at-least-once — the service calls
|
|
5124
|
-
* `tryClaim` as an atomic race guard BEFORE it triggers the final
|
|
5125
|
-
* activation.
|
|
5126
|
-
*/
|
|
5127
|
-
interface PaymentEventLog {
|
|
5128
|
-
/**
|
|
5129
|
-
* Tries to insert an event record via `@unique` INSERT. Returns
|
|
5130
|
-
* `true` if it was newly created (webhook seen for the first time),
|
|
5131
|
-
* `false` if it already exists (duplicate → silently drop).
|
|
5132
|
-
*
|
|
5133
|
-
* Implementations must return a DB unique-constraint-violation error
|
|
5134
|
-
* (Prisma P2002) as `false`.
|
|
5135
|
-
*/
|
|
5136
|
-
tryClaim(eventId: string, payload: {
|
|
5137
|
-
provider: string;
|
|
5138
|
-
sessionId: string | null;
|
|
5139
|
-
status: PaymentEventStatus;
|
|
5140
|
-
rawPayload?: unknown;
|
|
5141
|
-
}): Promise<boolean>;
|
|
5142
|
-
}
|
|
5143
5824
|
interface FinalActivationResult {
|
|
5144
5825
|
userId: string;
|
|
5145
5826
|
tenantId: string;
|
|
5146
5827
|
subscriptionId: string;
|
|
5828
|
+
/**
|
|
5829
|
+
* The subscriber created for the tenant in the same transaction — the party
|
|
5830
|
+
* its contracts are concluded with. `subscriberFromRegistration(pending)`
|
|
5831
|
+
* says what it is created with.
|
|
5832
|
+
*/
|
|
5833
|
+
subscriberId: string;
|
|
5834
|
+
}
|
|
5835
|
+
/** The transaction a sign-up is activated on. */
|
|
5836
|
+
interface RegistrationActivation {
|
|
5837
|
+
/**
|
|
5838
|
+
* Opened by the platform, which has already claimed the gateway's
|
|
5839
|
+
* confirmation on it and records the confirmed payment method on it once
|
|
5840
|
+
* `activate` returns. Every row the activation writes goes through it, so
|
|
5841
|
+
* a failure anywhere rolls back all of it — the claim included, and the
|
|
5842
|
+
* gateway's retry is handled rather than discarded as a duplicate.
|
|
5843
|
+
*/
|
|
5844
|
+
tx: TransactionContext;
|
|
5147
5845
|
}
|
|
5148
5846
|
/**
|
|
5149
|
-
* Adapter port:
|
|
5150
|
-
*
|
|
5151
|
-
* own schema (e.g. Tenant + TenantUser + Role + UserRole +
|
|
5152
|
-
* Subscription).
|
|
5847
|
+
* Adapter port: creates User + Tenant + Subscriber + Subscription once the
|
|
5848
|
+
* gateway confirmed the sign-up's payment method. App-specific — each app has
|
|
5849
|
+
* its own schema (e.g. Tenant + TenantUser + Role + UserRole + Subscription).
|
|
5153
5850
|
*
|
|
5154
|
-
* Implementations
|
|
5155
|
-
*
|
|
5851
|
+
* Implementations write on `activation.tx` and open no transaction of their
|
|
5852
|
+
* own: a write beside it would survive the rollback that undoes the rest. The
|
|
5853
|
+
* subscriber is created there too, before any contract:
|
|
5854
|
+
* `SubscriberService.createForTenant(tenantId, subscriberFromRegistration(pending),
|
|
5855
|
+
* activation.tx)`, or `CheckoutOfferService.conclude` with `subscriber` and
|
|
5856
|
+
* that transaction.
|
|
5156
5857
|
*/
|
|
5157
5858
|
interface ActivationOrchestrator {
|
|
5158
|
-
activate(pending: PendingRegistration): Promise<FinalActivationResult>;
|
|
5159
|
-
}
|
|
5160
|
-
interface HandlePaymentEventInput {
|
|
5161
|
-
eventId: string;
|
|
5162
|
-
sessionId: string | null;
|
|
5163
|
-
provider: string;
|
|
5164
|
-
status: PaymentEventStatus;
|
|
5165
|
-
rawPayload?: unknown;
|
|
5166
|
-
}
|
|
5167
|
-
type HandlePaymentEventReason = 'ALREADY_PROCESSED' | 'PAYMENT_NOT_SUCCEEDED' | 'MISSING_SESSION_ID' | 'PENDING_REGISTRATION_NOT_FOUND' | 'INVALID_STATE';
|
|
5168
|
-
interface HandlePaymentEventResult {
|
|
5169
|
-
activated: boolean;
|
|
5170
|
-
reason?: HandlePaymentEventReason;
|
|
5171
|
-
result?: FinalActivationResult;
|
|
5859
|
+
activate(pending: PendingRegistration, activation: RegistrationActivation): Promise<FinalActivationResult>;
|
|
5172
5860
|
}
|
|
5173
5861
|
interface CleanupResult {
|
|
5174
5862
|
/** Number of deleted PendingRegistration records. */
|
|
@@ -5179,7 +5867,7 @@ interface CleanupResult {
|
|
|
5179
5867
|
*/
|
|
5180
5868
|
moreAvailable: boolean;
|
|
5181
5869
|
}
|
|
5182
|
-
type RegistrationAuditEventType = 'REGISTRATION_STARTED' | 'REGISTRATION_NEUTRAL_ACTIVE_USER' | 'REGISTRATION_NEUTRAL_REPLAY' | 'REGISTRATION_NEUTRAL_EXPIRED' | 'OTP_VERIFIED' | 'OTP_VERIFY_FAILED' | 'OTP_RESEND_REQUESTED' | 'OTP_RATE_LIMIT_HIT' | 'PLAN_SELECTED' | 'CHECKOUT_STARTED' | 'PAYMENT_RECEIVED' | '
|
|
5870
|
+
type RegistrationAuditEventType = 'REGISTRATION_STARTED' | 'REGISTRATION_NEUTRAL_ACTIVE_USER' | 'REGISTRATION_NEUTRAL_REPLAY' | 'REGISTRATION_NEUTRAL_EXPIRED' | 'OTP_VERIFIED' | 'OTP_VERIFY_FAILED' | 'OTP_RESEND_REQUESTED' | 'OTP_RATE_LIMIT_HIT' | 'PLAN_SELECTED' | 'CHECKOUT_STARTED' | 'PAYMENT_RECEIVED' | 'PAYMENT_FAILED' | 'ACTIVATION_COMPLETED' | 'LOGIN_SUCCEEDED' | 'LOGIN_INVALID_CREDENTIALS' | 'LOGIN_ONBOARDING_REQUIRED';
|
|
5183
5871
|
/**
|
|
5184
5872
|
* Context information that the audit layer records per event.
|
|
5185
5873
|
* IP is expected as a hashed fingerprint — no plaintext IPs in the
|
|
@@ -5426,6 +6114,8 @@ interface PendingRegistrationSnapshot {
|
|
|
5426
6114
|
config: RegistrationConfigSelection | null;
|
|
5427
6115
|
billingCycle: 'MONTHLY' | 'YEARLY' | null;
|
|
5428
6116
|
appliedPromoCode: string | null;
|
|
6117
|
+
/** The billing details step 4 already took, to fill its form again. */
|
|
6118
|
+
billingDetails: RegistrationBillingDetails | null;
|
|
5429
6119
|
checkoutSessionId: string | null;
|
|
5430
6120
|
}
|
|
5431
6121
|
interface ResumeRegistrationResult {
|
|
@@ -5434,27 +6124,6 @@ interface ResumeRegistrationResult {
|
|
|
5434
6124
|
nextStep: RegistrationStep;
|
|
5435
6125
|
snapshot: PendingRegistrationSnapshot;
|
|
5436
6126
|
}
|
|
5437
|
-
/** Adapter port: payment provider (Stripe, Dev-Stub, Mollie, ...). */
|
|
5438
|
-
interface PaymentProvider {
|
|
5439
|
-
/**
|
|
5440
|
-
* Creates a checkout session at the payment provider and returns the URL
|
|
5441
|
-
* that the frontend should redirect to.
|
|
5442
|
-
*
|
|
5443
|
-
* @param params.pendingRegistrationId Stored as `client_reference_id` (or similar)
|
|
5444
|
-
* in the provider — the webhook needs it to link back.
|
|
5445
|
-
* @param params.planId The chosen plan (Stripe price/product mapping lives
|
|
5446
|
-
* in the adapter).
|
|
5447
|
-
* @param params.successUrl Where to go after successful payment.
|
|
5448
|
-
* @param params.cancelUrl Where to go on cancellation.
|
|
5449
|
-
*/
|
|
5450
|
-
createCheckoutSession(params: {
|
|
5451
|
-
pendingRegistrationId: string;
|
|
5452
|
-
planId: string;
|
|
5453
|
-
email: string;
|
|
5454
|
-
successUrl: string;
|
|
5455
|
-
cancelUrl: string;
|
|
5456
|
-
}): Promise<CheckoutSession>;
|
|
5457
|
-
}
|
|
5458
6127
|
/** Adapter port: OTP delivery via email (or another channel). */
|
|
5459
6128
|
interface RegistrationOtpDelivery {
|
|
5460
6129
|
sendVerificationOtp(params: {
|
|
@@ -5520,9 +6189,27 @@ interface SelectPlanResult {
|
|
|
5520
6189
|
nextStep: RegistrationStep;
|
|
5521
6190
|
selectedPlanId: string;
|
|
5522
6191
|
}
|
|
6192
|
+
/**
|
|
6193
|
+
* The billing address and tax identifiers a sign-up gives in step 4, which its
|
|
6194
|
+
* subscriber is created with. The address is required; the tax identifiers
|
|
6195
|
+
* stay optional until the tax adapter says when one is needed.
|
|
6196
|
+
*/
|
|
6197
|
+
interface RegistrationBillingDetails {
|
|
6198
|
+
addressLine1: string;
|
|
6199
|
+
addressLine2?: string | null;
|
|
6200
|
+
postalCode: string;
|
|
6201
|
+
city: string;
|
|
6202
|
+
/** ISO 3166-1 alpha-2, upper case. */
|
|
6203
|
+
country: string;
|
|
6204
|
+
vatId?: string | null;
|
|
6205
|
+
taxNumber?: string | null;
|
|
6206
|
+
}
|
|
5523
6207
|
interface StartCheckoutInput {
|
|
5524
6208
|
pendingRegistrationId: string;
|
|
6209
|
+
billingDetails: RegistrationBillingDetails;
|
|
6210
|
+
/** Where the gateway's form sends the person once the payment method is set up. */
|
|
5525
6211
|
successUrl: string;
|
|
6212
|
+
/** Where the gateway's form sends the person who leaves it. */
|
|
5526
6213
|
cancelUrl: string;
|
|
5527
6214
|
}
|
|
5528
6215
|
interface StartCheckoutResult {
|
|
@@ -5617,10 +6304,106 @@ declare function toPlanRow(row: CanonicalPlanRow): PlanRow;
|
|
|
5617
6304
|
*/
|
|
5618
6305
|
declare function toPlanVersionRow(row: CanonicalPlanVersionRow, planKey: string, fields: PlanVersionMappingFields): PlanVersionRow;
|
|
5619
6306
|
|
|
6307
|
+
/** The fields a correction of the legal identity may change, in the order they are shown. */
|
|
6308
|
+
declare const SUBSCRIBER_IDENTITY_FIELDS: readonly SubscriberIdentityField[];
|
|
6309
|
+
/** A `subscribers` row as either adapter reads it back. */
|
|
6310
|
+
interface CanonicalSubscriberRow {
|
|
6311
|
+
id: string;
|
|
6312
|
+
customerSequence: number;
|
|
6313
|
+
customerNumberPrefix: string;
|
|
6314
|
+
legalName: string;
|
|
6315
|
+
addressLine1: string | null;
|
|
6316
|
+
addressLine2: string | null;
|
|
6317
|
+
postalCode: string | null;
|
|
6318
|
+
city: string | null;
|
|
6319
|
+
country: string | null;
|
|
6320
|
+
vatId: string | null;
|
|
6321
|
+
taxNumber: string | null;
|
|
6322
|
+
invoiceEmail: string | null;
|
|
6323
|
+
migrated: boolean;
|
|
6324
|
+
createdAt: Date;
|
|
6325
|
+
updatedAt: Date;
|
|
6326
|
+
}
|
|
6327
|
+
/** A `subscriber_corrections` row as either adapter reads it back. */
|
|
6328
|
+
interface CanonicalSubscriberCorrectionRow {
|
|
6329
|
+
id: string;
|
|
6330
|
+
subscriberId: string;
|
|
6331
|
+
previous: unknown;
|
|
6332
|
+
corrected: unknown;
|
|
6333
|
+
reason: string;
|
|
6334
|
+
correctedBy: string;
|
|
6335
|
+
correctedAt: Date;
|
|
6336
|
+
}
|
|
6337
|
+
/**
|
|
6338
|
+
* The customer number a subscriber is known by: the prefix it was assigned
|
|
6339
|
+
* with, then the number. Kept apart in storage so the number orders and the
|
|
6340
|
+
* prefix stays what it was on the day it was assigned.
|
|
6341
|
+
*/
|
|
6342
|
+
declare function formatCustomerNumber(prefix: string, sequence: number): string;
|
|
6343
|
+
/** `tenantId` is the tenant the subscriber's live link names, read beside the row. */
|
|
6344
|
+
declare function toSubscriberRecord(row: CanonicalSubscriberRow, tenantId: string | null): SubscriberRecord;
|
|
6345
|
+
declare function toSubscriberCorrectionRecord(row: CanonicalSubscriberCorrectionRow): SubscriberCorrectionRecord;
|
|
6346
|
+
/**
|
|
6347
|
+
* The part of a correction that changes something: every corrected field whose
|
|
6348
|
+
* stored value differs, with the value it replaces. Both adapters decide this
|
|
6349
|
+
* the same way, under the lock they read `current` with.
|
|
6350
|
+
*/
|
|
6351
|
+
declare function identityCorrectionDelta(current: Pick<SubscriberRecord, SubscriberIdentityField>, corrected: SubscriberIdentityValues): SubscriberIdentityDelta;
|
|
6352
|
+
/**
|
|
6353
|
+
* Who a new contract is between: the subscriber as it stands, and the issuer as
|
|
6354
|
+
* the running configuration names it — or no issuer, where it names none.
|
|
6355
|
+
*/
|
|
6356
|
+
declare function contractPartiesOf(subscriber: SubscriberRecord, issuer: PlanCatalog['issuer']): SubscriptionContractParties;
|
|
6357
|
+
/**
|
|
6358
|
+
* The subscriber a completed sign-up is created with: the name the tenant was
|
|
6359
|
+
* registered under as its legal name, the address the registration was
|
|
6360
|
+
* verified with as its invoice email, and the billing address and tax
|
|
6361
|
+
* identifiers step 4 took.
|
|
6362
|
+
*/
|
|
6363
|
+
declare function subscriberFromRegistration(pending: Pick<PendingRegistration, 'tenantName' | 'email' | 'addressLine1' | 'addressLine2' | 'postalCode' | 'city' | 'country' | 'vatId' | 'taxNumber'>): NewSubscriberDetails;
|
|
6364
|
+
|
|
6365
|
+
/** The payment method types, in the order a form offers them. */
|
|
6366
|
+
declare const PAYMENT_METHOD_TYPES: readonly PaymentMethodType[];
|
|
6367
|
+
/** A `subscriber_payment_methods` row as either adapter reads it back. */
|
|
6368
|
+
interface CanonicalSubscriberPaymentMethodRow {
|
|
6369
|
+
id: string;
|
|
6370
|
+
subscriberId: string;
|
|
6371
|
+
gatewayAccount: string;
|
|
6372
|
+
provider: string;
|
|
6373
|
+
customerRef: string;
|
|
6374
|
+
paymentMethodRef: string;
|
|
6375
|
+
type: string;
|
|
6376
|
+
brand: string | null;
|
|
6377
|
+
last4: string;
|
|
6378
|
+
expiryMonth: number | null;
|
|
6379
|
+
expiryYear: number | null;
|
|
6380
|
+
country: string | null;
|
|
6381
|
+
bankCode: string | null;
|
|
6382
|
+
mandateReference: string | null;
|
|
6383
|
+
status: string;
|
|
6384
|
+
confirmedAt: Date;
|
|
6385
|
+
replacedAt: Date | null;
|
|
6386
|
+
createdAt: Date;
|
|
6387
|
+
}
|
|
6388
|
+
/**
|
|
6389
|
+
* Reads a row back as a record.
|
|
6390
|
+
*
|
|
6391
|
+
* The two text columns with a closed set of values are checked rather than
|
|
6392
|
+
* cast: a value written by hand or by an older release would otherwise reach a
|
|
6393
|
+
* screen as a type nobody handles.
|
|
6394
|
+
*/
|
|
6395
|
+
declare function toSubscriberPaymentMethodRecord(row: CanonicalSubscriberPaymentMethodRow): SubscriberPaymentMethodRecord;
|
|
6396
|
+
/** The columns a confirmed payment method is written with, and nothing a caller added beside them. */
|
|
6397
|
+
declare function subscriberPaymentMethodColumns(data: RecordSubscriberPaymentMethodData): Omit<CanonicalSubscriberPaymentMethodRow, 'id' | 'status' | 'replacedAt' | 'createdAt'>;
|
|
6398
|
+
|
|
5620
6399
|
/** A `subscription_contracts` row as either adapter reads it back. */
|
|
5621
6400
|
interface CanonicalContractRow {
|
|
5622
6401
|
id: string;
|
|
5623
6402
|
tenantId: string;
|
|
6403
|
+
subscriberId: string;
|
|
6404
|
+
subscriberSnapshot: unknown;
|
|
6405
|
+
issuerSnapshot: unknown;
|
|
6406
|
+
partiesMigrated: boolean;
|
|
5624
6407
|
status: string;
|
|
5625
6408
|
effectiveFrom: Date;
|
|
5626
6409
|
effectiveUntil: Date | null;
|
|
@@ -5742,4 +6525,4 @@ declare function resolveErrorMessage(body: ResolvableErrorBody, overrides?: Part
|
|
|
5742
6525
|
|
|
5743
6526
|
declare const ERROR_MESSAGES_DE: Record<PlatformErrorCode, string>;
|
|
5744
6527
|
|
|
5745
|
-
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 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 CheckoutSession, type CleanupResult, type CliUserRow, type ComponentKey, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ContractErrorCode, type ContractLineItemKind, type ContractLineItemRecord, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, 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 HandlePaymentEventInput, type HandlePaymentEventReason, type HandlePaymentEventResult, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type KpiCardDef, type KpiDisplayHint, 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 MfaPort, type NewContractLineItemData, type NewSettingsChange, 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, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PasswordHasher, type PasswordResetCliResult, type PaymentEventLog, type PaymentEventStatus, type PaymentProvider, 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 PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogNotifications, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, 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 RedeemPromoInTransactionCallback, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, 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, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, 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 StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, 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, classifyPlanDiff, collectUnsatisfiedRequires, coverageExcludingSelf, definedFields, diffSettings, formatErrorMessage, isBundleRedundant, isPlatformUserExistsError, isVersionEditable, keepOneRecommended, missingRequiresFor, pickActivePromo, previousUtcDay, promoStatus, readQuotaRecord, readQuotaValue, resolveBundleAvailability, resolveErrorMessage, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, toBundleStemRow, toContractLineItemRecord, toPlanRow, toPlanVersionRow, toSubscriptionContractRecord };
|
|
6528
|
+
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 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 KpiCardDef, type KpiDisplayHint, type LegalIdentity, 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 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, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ERROR_CODES, SUBSCRIBER_IDENTITY_FIELDS, 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 SubscriberIdentityField, 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, classifyPlanDiff, collectUnsatisfiedRequires, contractPartiesOf, coverageExcludingSelf, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, identityCorrectionDelta, isBundleRedundant, isPaymentCallbackRejectedError, isPlatformUserExistsError, isVersionEditable, keepOneRecommended, missingRequiresFor, pickActivePromo, planCatalogSettingsOf, previousUtcDay, promoStatus, readQuotaRecord, readQuotaValue, resolveBundleAvailability, resolveErrorMessage, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberFromRegistration, subscriberPaymentMethodColumns, toBundleStemRow, toContractLineItemRecord, toPlanRow, toPlanVersionRow, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriptionContractRecord };
|