@saasicat/core 1.0.0-rc.24 → 1.0.0-rc.25

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
@@ -878,6 +878,13 @@ interface PlanCatalogPayments {
878
878
  /** Every account taking new payment methods or holding a reference in use. */
879
879
  accounts: Record<string, PlanCatalogPaymentAccount>;
880
880
  }
881
+ /** `config/saas.yaml#tax`: the adapter an installation names, and what the operator declares to it. */
882
+ interface PlanCatalogTax {
883
+ /** The adapter's package name, such as `@saasicat/tax-de`. */
884
+ adapter: string;
885
+ /** The options the adapter's factory builds it with; the factory checks them. */
886
+ options?: Record<string, unknown>;
887
+ }
881
888
  /**
882
889
  * The part of `config/saas.yaml` that is configuration rather than catalogue.
883
890
  *
@@ -890,8 +897,15 @@ interface PlanCatalogSettings {
890
897
  app: PlanCatalogApp;
891
898
  /** ISO-4217 currency code. */
892
899
  currency: string;
893
- /** VAT rate in percent. */
894
- vatRate: number;
900
+ /**
901
+ * VAT rate in percent. Every installation names it unless `tax` names a
902
+ * tax adapter, which is then the one source of every rate.
903
+ */
904
+ vatRate?: number;
905
+ /** The tax adapter that decides each charge's treatment, and its options. */
906
+ tax?: PlanCatalogTax;
907
+ /** The installation's time zone, an IANA name; required with `tax` (`SC-PRIC-045`). */
908
+ timeZone?: string;
895
909
  /** Commercial settings for the tenant self-service routes. */
896
910
  tenantBilling: PlanCatalogTenantBilling;
897
911
  /** App-wide marketing configuration. Optional. */
@@ -1006,48 +1020,574 @@ interface PromoCodeValidationLog {
1006
1020
  result: PromoCodeValidationResult;
1007
1021
  createdAt: string;
1008
1022
  }
1009
-
1023
+
1024
+ /**
1025
+ * A tenant's own limits beside its plan — a negotiated contract, a pilot.
1026
+ * `quotas[key]` replaces the plan's value for that quota, `-1` meaning
1027
+ * unlimited; `features` adds to the plan's. Stored as JSON in
1028
+ * `subscriptions.customLimits`.
1029
+ */
1030
+ interface CustomLimits {
1031
+ quotas?: Record<QuotaKey, number>;
1032
+ features?: FeatureKey[];
1033
+ }
1034
+ /**
1035
+ * The keys a stored `customLimits` value is read by. The normative admin API
1036
+ * schema (`CustomLimits` in `@saasicat/spec`) is held to the same list.
1037
+ */
1038
+ declare const CUSTOM_LIMITS_KEYS: readonly ["quotas", "features"];
1039
+ /** What a stored `customLimits` value gave, and what in it went unread. */
1040
+ interface ReadCustomLimits {
1041
+ limits: CustomLimits | null;
1042
+ /**
1043
+ * The parts of the stored value the platform does not read — a key it does
1044
+ * not know, or a `quotas`/`features` of the wrong kind. Empty when every
1045
+ * part was read.
1046
+ */
1047
+ unread: string[];
1048
+ }
1049
+ /**
1050
+ * Reads a stored `customLimits` value the way the platform applies it.
1051
+ *
1052
+ * A shape the platform does not read is reported rather than refused: the
1053
+ * tenant keeps its plan's limits and goes on working, as a limit nothing can
1054
+ * count does not block anybody (`SC-ENTL-010`), and the caller says out loud
1055
+ * which limits were not applied. Each quota value goes through
1056
+ * `readQuotaValue`, the one reading of a quota in JSON.
1057
+ */
1058
+ declare function readCustomLimits(value: unknown): ReadCustomLimits;
1059
+ /**
1060
+ * Reads stored limits for an adapter, and reports what went unread once per
1061
+ * subscription — every entitlement read passes through here, so reporting on
1062
+ * each would bury the one line an operator needs under thousands.
1063
+ */
1064
+ declare function customLimitsReader(report: (line: string) => void): (subscriptionId: string, stored: unknown) => CustomLimits | null;
1065
+
1066
+ /** Alias for historical compatibility — equivalent to VersionChangeDirection. */
1067
+ type ChangeDirection = VersionChangeDirection;
1068
+ interface DiffResult {
1069
+ nonRegressive: boolean;
1070
+ changes: VersionChange[];
1071
+ }
1072
+ /**
1073
+ * `Decimal | string | number` — the three forms in which prices appear
1074
+ * in the platform. `Decimal` is the Prisma class (with
1075
+ * `.toNumber()`), which is not imported directly in order to keep the
1076
+ * platform Prisma-free — a structural view suffices.
1077
+ */
1078
+ type DecimalLike = number | string | {
1079
+ toNumber(): number;
1080
+ };
1081
+ interface PlanVersionFields {
1082
+ features: FeatureKey[];
1083
+ /**
1084
+ * Quotas of the version. -1 = unlimited; missing key = 0.
1085
+ *
1086
+ * Every key either side carries is compared. Which keys exist is the
1087
+ * installation's decision — they come from `@DefinesQuota` — so a fixed
1088
+ * set here would have compared the three the platform happened to know by
1089
+ * name and let every other one be lowered without the confirmation
1090
+ * publishing a regression asks for.
1091
+ */
1092
+ quotas: Record<QuotaKey, number>;
1093
+ monthlyNet: DecimalLike;
1094
+ yearlyNet: DecimalLike;
1095
+ }
1096
+ interface BundleVersionFields {
1097
+ features: FeatureKey[];
1098
+ /** Quota contributions of the bundle. -1 = unlimited; missing key = 0. */
1099
+ quotas: Record<QuotaKey, number>;
1100
+ /** Default pricing; null = only override pricing possible. */
1101
+ monthlyNet: DecimalLike | null;
1102
+ yearlyNet: DecimalLike | null;
1103
+ }
1104
+ declare function classifyPlanDiff(oldV: PlanVersionFields, newV: PlanVersionFields): DiffResult;
1105
+ /**
1106
+ * Classification of a BundleVersion diff for contract protection.
1107
+ *
1108
+ * Quotas are compared exactly as they are for a plan.
1109
+ *
1110
+ * Pricing can be `null` (the bundle only has override pricing); a switch
1111
+ * from value ↔ null is classified as REGRESSION (value dropped) or IMPROVEMENT
1112
+ * (value added, lowerIsBetter inverted). Both null
1113
+ * stay NEUTRAL.
1114
+ */
1115
+ declare function classifyBundleVersionDiff(oldV: BundleVersionFields, newV: BundleVersionFields): DiffResult;
1116
+
1117
+ /**
1118
+ * - `improvement` — nothing dearer in any rhythm, no feature missing, no quota
1119
+ * lower. Taken at once and free, the term kept.
1120
+ * - `more-for-more` — nothing missing or lower, but dearer in at least one
1121
+ * rhythm. Taken like an upgrade: at once, the difference prorated. The rule
1122
+ * reads every rhythm, so in the subscriber's own the difference can be zero
1123
+ * or below — monthly 49 to 45 with yearly 490 to 500 is more for more for a
1124
+ * monthly subscriber too.
1125
+ * - `takes-something-away` — a feature missing or a quota lower, whatever the
1126
+ * price. Taken like a downgrade: at the end of the running term, and only
1127
+ * when the subscriber asks for it.
1128
+ * - `same` — the two agree on everything compared: there is nothing to offer.
1129
+ */
1130
+ type VersionOfferClass = 'improvement' | 'more-for-more' | 'takes-something-away' | 'same';
1131
+ /**
1132
+ * A version as the comparison reads it. A price may be absent: that is a
1133
+ * rhythm the version is not sold in, and a rhythm that stops being sold counts
1134
+ * against the candidate like a price that went up.
1135
+ */
1136
+ type VersionOfferFields = BundleVersionFields;
1137
+ interface VersionOffer {
1138
+ readonly class: VersionOfferClass;
1139
+ /** Every difference, bound to candidate, as the catalogue's diff states it. */
1140
+ readonly changes: readonly VersionChange[];
1141
+ }
1142
+ /** One version as a subscriber compares it. A price of null is a rhythm it is not sold in. */
1143
+ interface VersionOfferSide {
1144
+ readonly planVersionId: string;
1145
+ readonly version: number;
1146
+ readonly features: readonly string[];
1147
+ readonly quotas: Readonly<Record<string, number>>;
1148
+ readonly monthlyNet: number | null;
1149
+ readonly yearlyNet: number | null;
1150
+ /** The last day it is sold on, where a successor closes its window — ISO, the whole day included. */
1151
+ readonly validUntil: string | null;
1152
+ /** When an operator ended it, where one did — ISO; from then it is not sold. */
1153
+ readonly endsAt: string | null;
1154
+ }
1155
+ /**
1156
+ * A newer version of the subscriber's plan, offered: the version bound and the
1157
+ * one offered side by side, what kind of offer it is, and when a switch taken
1158
+ * now would take effect — at once, or, for one that takes something away, at
1159
+ * the end of the running term. `GET billing/version-offer` answers with it.
1160
+ */
1161
+ interface VersionOfferView {
1162
+ readonly plan: string;
1163
+ readonly bound: VersionOfferSide;
1164
+ readonly offered: VersionOfferSide;
1165
+ readonly class: Exclude<VersionOfferClass, 'same'>;
1166
+ readonly changes: readonly VersionChange[];
1167
+ /** ISO instant. */
1168
+ readonly takesEffectAt: string;
1169
+ }
1170
+ /**
1171
+ * What taking an offer did: the version left and the one taken, and whether it
1172
+ * applied at once or waits for `takesEffectAt`. `POST billing/version-offer/accept`
1173
+ * answers with it.
1174
+ */
1175
+ interface VersionSwitchResult {
1176
+ readonly class: Exclude<VersionOfferClass, 'same'>;
1177
+ readonly fromPlanVersionId: string;
1178
+ readonly planVersionId: string;
1179
+ readonly immediate: boolean;
1180
+ /** ISO instant. */
1181
+ readonly takesEffectAt: string;
1182
+ }
1183
+ /**
1184
+ * Classifies `candidate` against `bound`. The comparison is the catalogue's
1185
+ * own diff — prices with a rhythm that may be absent, as a bundle version's
1186
+ * are — so an offer and a published version describe their changes alike.
1187
+ */
1188
+ declare function classifyVersionOffer(bound: VersionOfferFields, candidate: VersionOfferFields): VersionOffer;
1189
+
1190
+ /** A version, as an announcement names it. */
1191
+ interface RetiredVersionRef {
1192
+ readonly planVersionId: string;
1193
+ readonly planKey: string;
1194
+ readonly version: number;
1195
+ }
1196
+ /** An announcement as it is kept: one per retirement, whoever it reaches. */
1197
+ interface VersionRetirementRecord {
1198
+ readonly id: string;
1199
+ /** The version retired. */
1200
+ readonly retired: RetiredVersionRef;
1201
+ /** The version its subscriptions continue on, named by the operator. */
1202
+ readonly replacement: RetiredVersionRef;
1203
+ readonly announcedAt: Date;
1204
+ /** Who announced it — an actor tag, as the audit log writes it. */
1205
+ readonly announcedBy: string;
1206
+ }
1207
+ type NewVersionRetirement = Omit<VersionRetirementRecord, 'id'>;
1208
+ /**
1209
+ * The manifest capability that announces retiring a version. The platform sets
1210
+ * it where it serves the routes, and the admin UI offers the action only where
1211
+ * it is set. Whether the operator's terms allow it is a blocker the preview
1212
+ * reports, so an operator who has not confirmed them learns what is missing.
1213
+ */
1214
+ declare const VERSION_RETIREMENT_CAPABILITY = "planVersions.retire";
1215
+ /**
1216
+ * One of the two versions of a retirement, as the subscriber compares them:
1217
+ * price in each rhythm, quotas and features, with the plan it belongs to — the
1218
+ * replacement may be a version of another plan.
1219
+ */
1220
+ interface RetirementSide extends VersionOfferSide {
1221
+ readonly planKey: string;
1222
+ }
1223
+ /**
1224
+ * A plan version a subscription is on is being retired, and the subscription
1225
+ * continues on the named replacement from its effective date. Sent once per
1226
+ * subscription and retirement, when the retirement is announced, and kept as
1227
+ * it was sent: the record shows what the subscriber was told, prices included.
1228
+ */
1229
+ interface VersionRetiredNotice {
1230
+ readonly kind: 'version-retired';
1231
+ readonly tenantId: string;
1232
+ readonly subscriptionId: string;
1233
+ readonly retirementId: string;
1234
+ readonly retired: RetirementSide;
1235
+ readonly replacement: RetirementSide;
1236
+ /** Every difference, retired to replacement, as the catalogue's diff states it. */
1237
+ readonly changes: readonly VersionChange[];
1238
+ /**
1239
+ * The rhythm the subscription is billed in when the retirement takes
1240
+ * effect — a change of rhythm scheduled by then included — which says
1241
+ * which of the two prices applies.
1242
+ */
1243
+ readonly billingCycle: string;
1244
+ /** ISO 8601. */
1245
+ readonly effectiveAt: string;
1246
+ /** ISO date (`YYYY-MM-DD`), UTC. */
1247
+ readonly lastDayToCancel: string;
1248
+ }
1249
+ /**
1250
+ * The one reminder of a retirement, where staying put costs the subscription
1251
+ * something (`SC-SUB-034`): sent 14 days before the retirement takes effect,
1252
+ * once per subscription and retired version. It says again what the
1253
+ * retirement notice said, and what a switch taken now would cost. Its
1254
+ * `billingCycle` is still the rhythm billed at the date, read again from the
1255
+ * subscription as it stands when the reminder is sent: a change of rhythm
1256
+ * scheduled since the announcement is in it.
1257
+ */
1258
+ interface VersionRetirementReminder extends Omit<VersionRetiredNotice, 'kind'> {
1259
+ readonly kind: 'version-retirement-reminder';
1260
+ /**
1261
+ * What switching to the replacement now costs in the subscription's rhythm
1262
+ * (`SC-SUB-032`), or null where it cannot switch now: in a trial, with a
1263
+ * change scheduled, or where either plan is held for a special contract.
1264
+ */
1265
+ readonly switchTerms: RetirementSwitchTerms | null;
1266
+ }
1267
+ /**
1268
+ * Why a retirement does not reach a subscription on the version:
1269
+ *
1270
+ * - `ended` — the subscription is over.
1271
+ * - `cancelled-before` — its cancellation lands by the effective date.
1272
+ * - `changes-before` — a scheduled change moves it to another plan, or to
1273
+ * another version of this one, by then.
1274
+ * - `no-term` — it carries no date a term can be counted from.
1275
+ * - `already-told` — an earlier announcement of this version reached it, and
1276
+ * stands.
1277
+ */
1278
+ type RetirementSkipReason = 'ended' | 'cancelled-before' | 'changes-before' | 'no-term' | 'already-told';
1279
+ /** A refusal as the preview reports it and the announcement throws it. */
1280
+ interface RetirementBlocker {
1281
+ readonly code: string;
1282
+ readonly message: string;
1283
+ readonly params: Record<string, string | number>;
1284
+ }
1285
+ /** A subscription a retirement reaches, with what it means there. */
1286
+ interface RetirementReachedRow {
1287
+ readonly tenantId: string;
1288
+ readonly subscriptionId: string;
1289
+ readonly status: string;
1290
+ /** The rhythm it is billed in when the retirement takes effect. */
1291
+ readonly billingCycle: string;
1292
+ /** ISO 8601. */
1293
+ readonly effectiveAt: string;
1294
+ /** ISO date, UTC. */
1295
+ readonly lastDayToCancel: string;
1296
+ /** Reached by another retirement within the last twelve months: the announcement waits. */
1297
+ readonly reachedRecently: boolean;
1298
+ }
1299
+ /** A subscription on the version a retirement does not reach, and why. */
1300
+ interface RetirementSkippedRow {
1301
+ readonly tenantId: string;
1302
+ readonly subscriptionId: string;
1303
+ readonly reason: RetirementSkipReason;
1304
+ }
1305
+ /** What announcing a retirement now would do. */
1306
+ interface RetirementPreview {
1307
+ readonly retired: RetirementSide;
1308
+ readonly replacement: RetirementSide;
1309
+ /** Every difference, retired to replacement, as the subscribers will be told it. */
1310
+ readonly changes: readonly VersionChange[];
1311
+ /** ISO 8601: the moment it is computed for. */
1312
+ readonly asOf: string;
1313
+ readonly reached: readonly RetirementReachedRow[];
1314
+ readonly skipped: readonly RetirementSkippedRow[];
1315
+ /** Empty where it may be announced as it stands. */
1316
+ readonly blockers: readonly RetirementBlocker[];
1317
+ }
1318
+ /** What an announcement did. */
1319
+ interface RetirementAnnounced {
1320
+ readonly retirement: VersionRetirementRecord;
1321
+ /** Notices sent now; the rest are sent by the next run. */
1322
+ readonly told: number;
1323
+ readonly failed: number;
1324
+ }
1325
+ /**
1326
+ * Why a notice not told yet waits — for a subscription a plan version's
1327
+ * retirement reached, or a booking an add-on version's did. The run that sends
1328
+ * the notices asks the same questions in the same order.
1329
+ */
1330
+ interface NotToldReasons {
1331
+ /**
1332
+ * What the notice announces would not fit at its date: the replacement's
1333
+ * plan could not carry the add-ons held then, or the replacement add-on
1334
+ * could not run beside a plan the booking meets. It waits until it would.
1335
+ */
1336
+ readonly doesNotFit: number;
1337
+ /** Told of another retirement within the last twelve months: it waits until those are over. */
1338
+ readonly twelveMonths: number;
1339
+ /**
1340
+ * No longer reached: something of the subscriber's own — a change taking
1341
+ * it off the version, a cancellation landing first — came before the date.
1342
+ * It will not be sent.
1343
+ */
1344
+ readonly noLongerReached: number;
1345
+ /** Nothing holds it back: it has reached nobody yet, and the next run tries again. */
1346
+ readonly nobodyYet: number;
1347
+ }
1348
+ /**
1349
+ * How far a retirement has come, counted over the subscriptions — or, for an
1350
+ * add-on version, the bookings — it reached (`SC-SUB-033`, `SC-BUN-053`).
1351
+ */
1352
+ interface RetirementProgress {
1353
+ /** Off the retired version: moved at their date, switched early, or changed on their own. */
1354
+ readonly moved: number;
1355
+ /** Still on the retired version, before their date. */
1356
+ readonly waiting: number;
1357
+ /** Still on the retired version after their date: the run has not moved them yet, or cannot. */
1358
+ readonly overdue: number;
1359
+ /**
1360
+ * Still on the retired version, and ended by their date: there is nothing
1361
+ * to move. A booking that ended after its date, before a move came, counts
1362
+ * here too: nothing moves a booking that has ended.
1363
+ */
1364
+ readonly ended: number;
1365
+ /**
1366
+ * Still on the retired version, and not told yet: their notice has reached
1367
+ * nobody, so their date is not set and nothing moves them (`SC-SUB-038`).
1368
+ */
1369
+ readonly notTold: number;
1370
+ /**
1371
+ * Why those counted `notTold` are not told yet, each counted once. Absent
1372
+ * from a server that does not count them.
1373
+ */
1374
+ readonly notToldReasons?: NotToldReasons;
1375
+ /**
1376
+ * Reminded 14 days before their date (`SC-SUB-034`) — counted beside the
1377
+ * four above, not instead of one: a subscription reminded moves later.
1378
+ */
1379
+ readonly reminded: number;
1380
+ }
1381
+ /** An announcement as the administration lists it, with how far it has come. */
1382
+ interface VersionRetirementView extends VersionRetirementRecord {
1383
+ readonly progress: RetirementProgress;
1384
+ }
1385
+ /** What one run of the moves at the date did. */
1386
+ interface RetirementMoveRun {
1387
+ /**
1388
+ * Subscriptions, or bookings, moved onto their replacement, with the
1389
+ * contract the move writes.
1390
+ */
1391
+ readonly moved: number;
1392
+ /** Moves that could not be made, and are tried again by the next run. */
1393
+ readonly failed: number;
1394
+ }
1395
+ /** What switching to the replacement before the date did (`SC-SUB-032`). */
1396
+ interface RetirementSwitchResult {
1397
+ readonly fromPlanVersionId: string;
1398
+ readonly planVersionId: string;
1399
+ /** ISO date of the last day the price is held, or null where none is. */
1400
+ readonly heldUntilDay: string | null;
1401
+ }
1402
+
1403
+ /** What the switch costs, per period of the subscriber's rhythm. */
1404
+ interface RetirementSwitchTerms {
1405
+ /** The replacement's net price. */
1406
+ readonly priceNet: number;
1407
+ /**
1408
+ * Where the replacement costs more: the price the subscriber goes on paying,
1409
+ * the difference that is held, and the last day it is held — the day before
1410
+ * the date they were told. Null where it costs the same or less: its price
1411
+ * then applies from the subscriber's next period.
1412
+ */
1413
+ readonly held: {
1414
+ readonly priceNet: number;
1415
+ readonly amountNet: number;
1416
+ readonly lastDay: string;
1417
+ } | null;
1418
+ }
1419
+ /**
1420
+ * A side of a retirement as its prices are compared: what it costs in each
1421
+ * rhythm, for a plan version or for an add-on version beside a plan.
1422
+ */
1423
+ type RetirementPricedSide = Pick<RetirementSide, 'monthlyNet' | 'yearlyNet'>;
1424
+ /**
1425
+ * What switching to the replacement now costs in `billingCycle`, or null where
1426
+ * the replacement has no price in it. A plan version's retirement and an add-on
1427
+ * version's are priced alike: each side by what it costs in each rhythm.
1428
+ */
1429
+ declare function retirementSwitchTerms(notice: {
1430
+ readonly retired: RetirementPricedSide;
1431
+ readonly replacement: RetirementPricedSide;
1432
+ readonly lastDayToCancel: string;
1433
+ }, billingCycle: string): RetirementSwitchTerms | null;
1434
+
1435
+ /** An add-on version, as an announcement names it. */
1436
+ interface RetiredBundleVersionRef {
1437
+ readonly bundleVersionId: string;
1438
+ readonly bundleKey: string;
1439
+ readonly version: number;
1440
+ }
1441
+ /** An add-on retirement as it is kept: one per announcement, whichever bookings it reaches. */
1442
+ interface BundleVersionRetirementRecord {
1443
+ readonly id: string;
1444
+ /** The version retired. */
1445
+ readonly retired: RetiredBundleVersionRef;
1446
+ /** The version of the same add-on its bookings continue on, named by the operator. */
1447
+ readonly replacement: RetiredBundleVersionRef;
1448
+ readonly announcedAt: Date;
1449
+ /** Who announced it — an actor tag, as the audit log writes it. */
1450
+ readonly announcedBy: string;
1451
+ }
1452
+ type NewBundleVersionRetirement = Omit<BundleVersionRetirementRecord, 'id'>;
1010
1453
  /**
1011
- * A tenant's own limits beside its plan — a negotiated contract, a pilot.
1012
- * `quotas[key]` replaces the plan's value for that quota, `-1` meaning
1013
- * unlimited; `features` adds to the plan's. Stored as JSON in
1014
- * `subscriptions.customLimits`.
1454
+ * The manifest capability that announces retiring an add-on version. The
1455
+ * platform sets it where it serves the routes, and the admin UI offers the
1456
+ * action only where it is set.
1015
1457
  */
1016
- interface CustomLimits {
1017
- quotas?: Record<QuotaKey, number>;
1018
- features?: FeatureKey[];
1458
+ declare const BUNDLE_VERSION_RETIREMENT_CAPABILITY = "bundleVersions.retire";
1459
+ /**
1460
+ * An add-on version as the subscriber compares it with another — the one
1461
+ * retired and its replacement, or the one booked and the one offered: what it
1462
+ * grants, and its price beside the subscription's plan in each rhythm —
1463
+ * `pricingOverrides` included — or null where it has none there.
1464
+ */
1465
+ interface BundleVersionSide {
1466
+ readonly bundleVersionId: string;
1467
+ readonly bundleKey: string;
1468
+ readonly label: string;
1469
+ readonly version: number;
1470
+ readonly features: readonly string[];
1471
+ readonly quotas: Readonly<Record<string, number>>;
1472
+ readonly monthlyNet: number | null;
1473
+ readonly yearlyNet: number | null;
1019
1474
  }
1020
1475
  /**
1021
- * The keys a stored `customLimits` value is read by. The normative admin API
1022
- * schema (`CustomLimits` in `@saasicat/spec`) is held to the same list.
1476
+ * An add-on version a booking is on is being retired, and the booking
1477
+ * continues on the named replacement from its effective date. Sent once per
1478
+ * booking and retirement, and kept as it was sent: the record shows what the
1479
+ * subscriber was told, prices included.
1023
1480
  */
1024
- declare const CUSTOM_LIMITS_KEYS: readonly ["quotas", "features"];
1025
- /** What a stored `customLimits` value gave, and what in it went unread. */
1026
- interface ReadCustomLimits {
1027
- limits: CustomLimits | null;
1028
- /**
1029
- * The parts of the stored value the platform does not read — a key it does
1030
- * not know, or a `quotas`/`features` of the wrong kind. Empty when every
1031
- * part was read.
1032
- */
1033
- unread: string[];
1481
+ interface BundleVersionRetiredNotice {
1482
+ readonly kind: 'bundle-version-retired';
1483
+ readonly tenantId: string;
1484
+ readonly subscriptionId: string;
1485
+ readonly subscriptionBundleId: string;
1486
+ readonly retirementId: string;
1487
+ /** The plan the add-on runs beside at the date, which both sides are priced for. */
1488
+ readonly planKey: string;
1489
+ readonly retired: BundleVersionSide;
1490
+ readonly replacement: BundleVersionSide;
1491
+ /** Every difference, retired to replacement, at the prices for `planKey`. */
1492
+ readonly changes: readonly VersionChange[];
1493
+ /** The rhythm the booking is billed in, which says which of the two prices applies. */
1494
+ readonly billingCycle: string;
1495
+ /** ISO 8601. */
1496
+ readonly effectiveAt: string;
1497
+ /** ISO date (`YYYY-MM-DD`), UTC: the last day it may be cancelled without its minimum term. */
1498
+ readonly lastDayToCancel: string;
1034
1499
  }
1035
1500
  /**
1036
- * Reads a stored `customLimits` value the way the platform applies it.
1501
+ * Why an add-on retirement does not reach a booking of the version:
1037
1502
  *
1038
- * A shape the platform does not read is reported rather than refused: the
1039
- * tenant keeps its plan's limits and goes on working, as a limit nothing can
1040
- * count does not block anybody (`SC-ENTL-010`), and the caller says out loud
1041
- * which limits were not applied. Each quota value goes through
1042
- * `readQuotaValue`, the one reading of a quota in JSON.
1503
+ * - `ended` — the subscription is over, or the booking's cancellation has
1504
+ * already landed.
1505
+ * - `cancelled-before` — the booking's cancellation lands by the effective date.
1506
+ * - `changes-before` — the booking's switch to a newer version, taken for the
1507
+ * end of its term, lands by the effective date.
1508
+ * - `no-term` — it carries no period an end can be counted from.
1509
+ * - `already-told` — an earlier announcement of this version reached it, and
1510
+ * stands.
1043
1511
  */
1044
- declare function readCustomLimits(value: unknown): ReadCustomLimits;
1512
+ type BundleRetirementSkipReason = 'ended' | 'cancelled-before' | 'changes-before' | 'no-term' | 'already-told';
1045
1513
  /**
1046
- * Reads stored limits for an adapter, and reports what went unread once per
1047
- * subscription — every entitlement read passes through here, so reporting on
1048
- * each would bury the one line an operator needs under thousands.
1514
+ * What switching a booking to its retirement's replacement now would cost
1515
+ * (`SC-BUN-054`), in the rhythm the booking is billed in now — its own, or
1516
+ * else its plan's — which need not be the one its notice was told in.
1049
1517
  */
1050
- declare function customLimitsReader(report: (line: string) => void): (subscriptionId: string, stored: unknown) => CustomLimits | null;
1518
+ interface BundleRetirementSwitchTerms extends RetirementSwitchTerms {
1519
+ readonly billingCycle: string;
1520
+ }
1521
+ /**
1522
+ * The one reminder of an add-on retirement (`SC-BUN-056`): sent once, 14 days
1523
+ * before the booking's date, where staying put costs it something. It says
1524
+ * again what the booking was told, with both versions priced for the plan the
1525
+ * add-on runs beside at the date as the catalogue prices them when it is sent,
1526
+ * in the rhythm the booking is billed in then.
1527
+ */
1528
+ interface BundleVersionRetirementReminder extends Omit<BundleVersionRetiredNotice, 'kind'> {
1529
+ readonly kind: 'bundle-version-retirement-reminder';
1530
+ /** What switching to the replacement now costs (`SC-BUN-054`), or null where the booking cannot. */
1531
+ readonly switchTerms: BundleRetirementSwitchTerms | null;
1532
+ }
1533
+ /** What switching a booking to its retirement's replacement before the date did. */
1534
+ interface BundleRetirementSwitchResult {
1535
+ readonly subscriptionBundleId: string;
1536
+ readonly fromBundleVersionId: string;
1537
+ readonly bundleVersionId: string;
1538
+ /** ISO date of the last day the price is held, or null where none is. */
1539
+ readonly heldUntilDay: string | null;
1540
+ }
1541
+ /** A booking an add-on retirement reaches, with what it means there. */
1542
+ interface BundleRetirementReachedRow {
1543
+ readonly tenantId: string;
1544
+ readonly subscriptionId: string;
1545
+ readonly subscriptionBundleId: string;
1546
+ /** The plan the add-on runs beside when the retirement takes effect. */
1547
+ readonly planKey: string;
1548
+ /** The rhythm the plan is billed in then. */
1549
+ readonly planCycle: string;
1550
+ /** The rhythm the booking is billed in. */
1551
+ readonly billingCycle: string;
1552
+ /** ISO 8601. */
1553
+ readonly effectiveAt: string;
1554
+ /** ISO date, UTC. */
1555
+ readonly lastDayToCancel: string;
1556
+ /** Its subscription was reached by a retirement within the last twelve months: the announcement waits. */
1557
+ readonly reachedRecently: boolean;
1558
+ }
1559
+ /** A booking of the version an add-on retirement does not reach, and why. */
1560
+ interface BundleRetirementSkippedRow {
1561
+ readonly tenantId: string;
1562
+ readonly subscriptionId: string;
1563
+ readonly subscriptionBundleId: string;
1564
+ readonly reason: BundleRetirementSkipReason;
1565
+ }
1566
+ /** What announcing an add-on retirement now would do. */
1567
+ interface BundleRetirementPreview {
1568
+ /** The two versions at their own prices, before any plan's override. */
1569
+ readonly retired: BundleVersionSide;
1570
+ readonly replacement: BundleVersionSide;
1571
+ /** Every difference at those prices; each booking is told the one at its plan's. */
1572
+ readonly changes: readonly VersionChange[];
1573
+ /** ISO 8601: the moment it is computed for. */
1574
+ readonly asOf: string;
1575
+ readonly reached: readonly BundleRetirementReachedRow[];
1576
+ readonly skipped: readonly BundleRetirementSkippedRow[];
1577
+ /** Empty where it may be announced as it stands. */
1578
+ readonly blockers: readonly RetirementBlocker[];
1579
+ }
1580
+ /** What an add-on announcement did. */
1581
+ interface BundleRetirementAnnounced {
1582
+ readonly retirement: BundleVersionRetirementRecord;
1583
+ /** Notices sent now; the rest are sent by the next run. */
1584
+ readonly told: number;
1585
+ readonly failed: number;
1586
+ }
1587
+ /** An add-on announcement as the administration lists it, with how far it has come. */
1588
+ interface BundleVersionRetirementView extends BundleVersionRetirementRecord {
1589
+ readonly progress: RetirementProgress;
1590
+ }
1051
1591
 
1052
1592
  type SubscriptionStatus = 'TRIAL' | 'ACTIVE' | 'PAST_DUE' | 'CANCELED' | 'PENDING_SALES';
1053
1593
  interface Subscription {
@@ -1145,9 +1685,11 @@ interface VersionedEntityBase {
1145
1685
  * their own minimum term + their own cancellation (user requirement from
1146
1686
  * P11.7.3).
1147
1687
  *
1148
- * - `bundleVersionId` binds the booking to an *exact* BundleVersion
1149
- * (immutable; bundle updates only take effect after a new version with its
1150
- * own migration).
1688
+ * - `bundleVersionId` binds the booking to an *exact* BundleVersion. A newer
1689
+ * version of the add-on does not change it by being published: an add-on
1690
+ * retirement moves the booking onto its replacement at its date
1691
+ * (`SC-BUN-049`), and the subscriber moves it by taking a newer version
1692
+ * offered (`SC-BUN-058`).
1151
1693
  * - `startedAt` is the contract start of this booking.
1152
1694
  * - `minimumTermEndsAt` = end of the minimum term; `null` = no minimum term
1153
1695
  * (platform default = no commitment, set service-side).
@@ -1179,6 +1721,15 @@ interface SubscriptionBundleRecord {
1179
1721
  billingCycle: BillingCycle | null;
1180
1722
  currentPeriodStart: Date | null;
1181
1723
  currentPeriodEnd: Date | null;
1724
+ /**
1725
+ * A switch to another version of the add-on, taken for the end of the
1726
+ * booking's running term because it takes something away (`SC-BUN-058`):
1727
+ * the version the booking continues on, and from when. Both null where
1728
+ * none is scheduled. The run that makes the switch at that moment clears
1729
+ * them; until then the booking stays on `bundleVersionId`.
1730
+ */
1731
+ pendingBundleVersionId: string | null;
1732
+ pendingVersionEffectiveAt: Date | null;
1182
1733
  createdAt: Date;
1183
1734
  updatedAt: Date;
1184
1735
  }
@@ -1202,6 +1753,18 @@ interface SubscriptionBundleView extends SubscriptionBundleRecord {
1202
1753
  * defect: a field called `monthlyNet` on a yearly booking cannot be right.
1203
1754
  */
1204
1755
  priceNet: number | null;
1756
+ /**
1757
+ * The number of the version a switch scheduled for the end of the booking's
1758
+ * term moves it to (`pendingBundleVersionId`); null where none is
1759
+ * scheduled.
1760
+ */
1761
+ pendingVersion?: number | null;
1762
+ /**
1763
+ * The retirement of the add-on version this booking is on, as the
1764
+ * subscriber was told it (`SC-BUN-046`); absent or null where none was
1765
+ * told, or once the booking is on another version.
1766
+ */
1767
+ retirement?: BundleVersionRetiredNotice | null;
1205
1768
  }
1206
1769
  interface CreateSubscriptionBundleData {
1207
1770
  subscriptionId: string;
@@ -2176,6 +2739,12 @@ interface PublicMarketingCatalogResponse {
2176
2739
  currency: string;
2177
2740
  /** VAT rate in percent — for the CheckoutOffer price breakdown. */
2178
2741
  vatRate: number;
2742
+ /**
2743
+ * The country the rate applies to: the issuer's, where a tax adapter
2744
+ * decides and a subscriber elsewhere may be charged another — the page says
2745
+ * so (`SC-PRIC-037`). `null` where the one rate of the file applies to all.
2746
+ */
2747
+ vatRateShownFor: string | null;
2179
2748
  /** What a new payment method is taken with here, if one is taken. */
2180
2749
  newPaymentMethods: PublicNewPaymentMethods;
2181
2750
  /** Visible, marketed plans — sorted by `priority` DESC. */
@@ -2268,202 +2837,78 @@ interface DiscoveredQuota {
2268
2837
  feature: string | null;
2269
2838
  /** Old quotaKeys that this quota replaces (#39). `null` = none. */
2270
2839
  replaces: string[] | null;
2271
- /** Where the quota is declared — `ClassName`. */
2272
- declaredAt: string;
2273
- /** Capability keys that reference this quota via `@EnforceQuota(quotaKey)`. */
2274
- enforcedBy: string[];
2275
- }
2276
- /**
2277
- * Complete discovery snapshot — built at boot time, delivered as JSON by
2278
- * the AdminController, checked against the DB catalog by the strict-mode
2279
- * check.
2280
- */
2281
- interface DiscoverySnapshot {
2282
- schemaVersion: 1;
2283
- /** ISO timestamp of the boot-time scan. */
2284
- scannedAt: string;
2285
- app: {
2286
- /** The application's name, from `saas.yaml#app.name`. */
2287
- key: string;
2288
- /** Backend version, e.g. from package.json. */
2289
- version: string;
2290
- };
2291
- capabilities: DiscoveredCapability[];
2292
- features: DiscoveredFeature[];
2293
- quotas: DiscoveredQuota[];
2294
- /**
2295
- * Canonical SHA256 hash over sorted/normalized snapshot data.
2296
- * Stable across boot restarts, serves as the ETag for `/admin/discovery`.
2297
- */
2298
- hash: string;
2299
- }
2300
-
2301
- interface EffectiveLimitsSnapshot {
2302
- plan: string;
2303
- quotas: Record<string, number>;
2304
- features: string[];
2305
- /**
2306
- * The add-ons a contract left out of these entitlements because their
2307
- * cancellation was already declared when it was written. Each is granted by
2308
- * its booking until its effective date, and by this snapshot never.
2309
- *
2310
- * Absent where nothing was left out — and on a snapshot written by an
2311
- * application, or before the platform left anything out, which then counts
2312
- * every add-on it names as its own.
2313
- */
2314
- leftOutBundleVersionIds?: string[];
2315
- }
2316
-
2317
- interface FeatureUiMeta {
2318
- /** Visible label for plan comparison tables, add-on lists. */
2319
- label: string;
2320
- /** Long description for tooltips, add-on cards. */
2321
- description: string;
2322
- /** Quasar icon name (e.g. 'directions_car', 'groups'). */
2323
- icon: string;
2324
- /** Mirror of `PlanCatalog.features[].plannedOnly` — cache for the UI without a catalog roundtrip. */
2325
- plannedOnly?: boolean;
2326
- /** true = base infrastructure, included in every plan (not bookable). */
2327
- core?: boolean;
2328
- }
2329
- /** Map FeatureKey → UI metadata. Consumer apps supply a complete table. */
2330
- type FeatureUiRegistry = Record<string, FeatureUiMeta>;
2331
-
2332
- /** A quota as a finite number, or `null` where the value cannot be read as one. */
2333
- declare function readQuotaValue(value: unknown): number | null;
2334
- /**
2335
- * Every quota in a JSON column, for a caller that computes with them.
2336
- *
2337
- * A key that is there stays there. Dropping an unreadable one made it *absent*,
2338
- * and absent means undeclared: `enforceLimit` answers an undeclared dimension
2339
- * with a 500, so every operation on that quota was refused — a fail-closed
2340
- * answer to somebody else's corrupt row.
2341
- */
2342
- declare function readQuotaRecord(value: unknown): Record<string, number>;
2343
-
2344
- /** Alias for historical compatibility — equivalent to VersionChangeDirection. */
2345
- type ChangeDirection = VersionChangeDirection;
2346
- interface DiffResult {
2347
- nonRegressive: boolean;
2348
- changes: VersionChange[];
2349
- }
2350
- /**
2351
- * `Decimal | string | number` — the three forms in which prices appear
2352
- * in the platform. `Decimal` is the Prisma class (with
2353
- * `.toNumber()`), which is not imported directly in order to keep the
2354
- * platform Prisma-free — a structural view suffices.
2355
- */
2356
- type DecimalLike = number | string | {
2357
- toNumber(): number;
2358
- };
2359
- interface PlanVersionFields {
2360
- features: FeatureKey[];
2361
- /**
2362
- * Quotas of the version. -1 = unlimited; missing key = 0.
2363
- *
2364
- * Every key either side carries is compared. Which keys exist is the
2365
- * installation's decision — they come from `@DefinesQuota` — so a fixed
2366
- * set here would have compared the three the platform happened to know by
2367
- * name and let every other one be lowered without the confirmation
2368
- * publishing a regression asks for.
2369
- */
2370
- quotas: Record<QuotaKey, number>;
2371
- monthlyNet: DecimalLike;
2372
- yearlyNet: DecimalLike;
2373
- }
2374
- interface BundleVersionFields {
2375
- features: FeatureKey[];
2376
- /** Quota contributions of the bundle. -1 = unlimited; missing key = 0. */
2377
- quotas: Record<QuotaKey, number>;
2378
- /** Default pricing; null = only override pricing possible. */
2379
- monthlyNet: DecimalLike | null;
2380
- yearlyNet: DecimalLike | null;
2381
- }
2382
- declare function classifyPlanDiff(oldV: PlanVersionFields, newV: PlanVersionFields): DiffResult;
2383
- /**
2384
- * Classification of a BundleVersion diff for contract protection.
2385
- *
2386
- * Quotas are compared exactly as they are for a plan.
2387
- *
2388
- * Pricing can be `null` (the bundle only has override pricing); a switch
2389
- * from value ↔ null is classified as REGRESSION (value dropped) or IMPROVEMENT
2390
- * (value added, lowerIsBetter inverted). Both null
2391
- * stay NEUTRAL.
2392
- */
2393
- declare function classifyBundleVersionDiff(oldV: BundleVersionFields, newV: BundleVersionFields): DiffResult;
2394
-
2395
- /**
2396
- * - `improvement` — nothing dearer in any rhythm, no feature missing, no quota
2397
- * lower. Taken at once and free, the term kept.
2398
- * - `more-for-more` — nothing missing or lower, but dearer in at least one
2399
- * rhythm. Taken like an upgrade: at once, the difference prorated. The rule
2400
- * reads every rhythm, so in the subscriber's own the difference can be zero
2401
- * or below — monthly 49 to 45 with yearly 490 to 500 is more for more for a
2402
- * monthly subscriber too.
2403
- * - `takes-something-away` — a feature missing or a quota lower, whatever the
2404
- * price. Taken like a downgrade: at the end of the running term, and only
2405
- * when the subscriber asks for it.
2406
- * - `same` — the two agree on everything compared: there is nothing to offer.
2407
- */
2408
- type VersionOfferClass = 'improvement' | 'more-for-more' | 'takes-something-away' | 'same';
2409
- /**
2410
- * A version as the comparison reads it. A price may be absent: that is a
2411
- * rhythm the version is not sold in, and a rhythm that stops being sold counts
2412
- * against the candidate like a price that went up.
2413
- */
2414
- type VersionOfferFields = BundleVersionFields;
2415
- interface VersionOffer {
2416
- readonly class: VersionOfferClass;
2417
- /** Every difference, bound to candidate, as the catalogue's diff states it. */
2418
- readonly changes: readonly VersionChange[];
2419
- }
2420
- /** One version as a subscriber compares it. A price of null is a rhythm it is not sold in. */
2421
- interface VersionOfferSide {
2422
- readonly planVersionId: string;
2423
- readonly version: number;
2424
- readonly features: readonly string[];
2425
- readonly quotas: Readonly<Record<string, number>>;
2426
- readonly monthlyNet: number | null;
2427
- readonly yearlyNet: number | null;
2428
- /** The last day it is sold on, where a successor closes its window — ISO, the whole day included. */
2429
- readonly validUntil: string | null;
2430
- /** When an operator ended it, where one did — ISO; from then it is not sold. */
2431
- readonly endsAt: string | null;
2840
+ /** Where the quota is declared — `ClassName`. */
2841
+ declaredAt: string;
2842
+ /** Capability keys that reference this quota via `@EnforceQuota(quotaKey)`. */
2843
+ enforcedBy: string[];
2432
2844
  }
2433
2845
  /**
2434
- * A newer version of the subscriber's plan, offered: the version bound and the
2435
- * one offered side by side, what kind of offer it is, and when a switch taken
2436
- * now would take effect — at once, or, for one that takes something away, at
2437
- * the end of the running term. `GET billing/version-offer` answers with it.
2846
+ * Complete discovery snapshot — built at boot time, delivered as JSON by
2847
+ * the AdminController, checked against the DB catalog by the strict-mode
2848
+ * check.
2438
2849
  */
2439
- interface VersionOfferView {
2440
- readonly plan: string;
2441
- readonly bound: VersionOfferSide;
2442
- readonly offered: VersionOfferSide;
2443
- readonly class: Exclude<VersionOfferClass, 'same'>;
2444
- readonly changes: readonly VersionChange[];
2445
- /** ISO instant. */
2446
- readonly takesEffectAt: string;
2850
+ interface DiscoverySnapshot {
2851
+ schemaVersion: 1;
2852
+ /** ISO timestamp of the boot-time scan. */
2853
+ scannedAt: string;
2854
+ app: {
2855
+ /** The application's name, from `saas.yaml#app.name`. */
2856
+ key: string;
2857
+ /** Backend version, e.g. from package.json. */
2858
+ version: string;
2859
+ };
2860
+ capabilities: DiscoveredCapability[];
2861
+ features: DiscoveredFeature[];
2862
+ quotas: DiscoveredQuota[];
2863
+ /**
2864
+ * Canonical SHA256 hash over sorted/normalized snapshot data.
2865
+ * Stable across boot restarts, serves as the ETag for `/admin/discovery`.
2866
+ */
2867
+ hash: string;
2447
2868
  }
2448
- /**
2449
- * What taking an offer did: the version left and the one taken, and whether it
2450
- * applied at once or waits for `takesEffectAt`. `POST billing/version-offer/accept`
2451
- * answers with it.
2452
- */
2453
- interface VersionSwitchResult {
2454
- readonly class: Exclude<VersionOfferClass, 'same'>;
2455
- readonly fromPlanVersionId: string;
2456
- readonly planVersionId: string;
2457
- readonly immediate: boolean;
2458
- /** ISO instant. */
2459
- readonly takesEffectAt: string;
2869
+
2870
+ interface EffectiveLimitsSnapshot {
2871
+ plan: string;
2872
+ quotas: Record<string, number>;
2873
+ features: string[];
2874
+ /**
2875
+ * The add-ons a contract left out of these entitlements because their
2876
+ * cancellation was already declared when it was written. Each is granted by
2877
+ * its booking until its effective date, and by this snapshot never.
2878
+ *
2879
+ * Absent where nothing was left out — and on a snapshot written by an
2880
+ * application, or before the platform left anything out, which then counts
2881
+ * every add-on it names as its own.
2882
+ */
2883
+ leftOutBundleVersionIds?: string[];
2460
2884
  }
2885
+
2886
+ interface FeatureUiMeta {
2887
+ /** Visible label for plan comparison tables, add-on lists. */
2888
+ label: string;
2889
+ /** Long description for tooltips, add-on cards. */
2890
+ description: string;
2891
+ /** Quasar icon name (e.g. 'directions_car', 'groups'). */
2892
+ icon: string;
2893
+ /** Mirror of `PlanCatalog.features[].plannedOnly` — cache for the UI without a catalog roundtrip. */
2894
+ plannedOnly?: boolean;
2895
+ /** true = base infrastructure, included in every plan (not bookable). */
2896
+ core?: boolean;
2897
+ }
2898
+ /** Map FeatureKey → UI metadata. Consumer apps supply a complete table. */
2899
+ type FeatureUiRegistry = Record<string, FeatureUiMeta>;
2900
+
2901
+ /** A quota as a finite number, or `null` where the value cannot be read as one. */
2902
+ declare function readQuotaValue(value: unknown): number | null;
2461
2903
  /**
2462
- * Classifies `candidate` against `bound`. The comparison is the catalogue's
2463
- * own diff — prices with a rhythm that may be absent, as a bundle version's
2464
- * are — so an offer and a published version describe their changes alike.
2904
+ * Every quota in a JSON column, for a caller that computes with them.
2905
+ *
2906
+ * A key that is there stays there. Dropping an unreadable one made it *absent*,
2907
+ * and absent means undeclared: `enforceLimit` answers an undeclared dimension
2908
+ * with a 500, so every operation on that quota was refused — a fail-closed
2909
+ * answer to somebody else's corrupt row.
2465
2910
  */
2466
- declare function classifyVersionOffer(bound: VersionOfferFields, candidate: VersionOfferFields): VersionOffer;
2911
+ declare function readQuotaRecord(value: unknown): Record<string, number>;
2467
2912
 
2468
2913
  interface PromoPreviewRequest {
2469
2914
  /** Promo code (case-insensitive, normalized to uppercase in the service). */
@@ -2656,292 +3101,127 @@ type MaintenanceWindowEvent = {
2656
3101
  } | {
2657
3102
  kind: 'cancelled';
2658
3103
  window: MaintenanceWindowRecord;
2659
- };
2660
- /** The longest message a window carries; the operator's words, not a document. */
2661
- declare const MAINTENANCE_MESSAGE_MAX_LENGTH = 500;
2662
- /**
2663
- * How long a process may go on reading a lock state it read before. Every
2664
- * request asks, so each process keeps the answer this long rather than asking
2665
- * the database per request; the command that locks waits this long before it
2666
- * returns, so that every process has seen the lock by then.
2667
- *
2668
- * Part of the contract between two versions of an application: the command
2669
- * that locks comes from the release being deployed, while the processes it
2670
- * waits for may still run the one before. It is safe only while the figure it
2671
- * waits by is at least theirs, so a later release may raise it and never lower
2672
- * it.
2673
- */
2674
- declare const MAINTENANCE_STATE_MAX_AGE_SECONDS = 5;
2675
- /**
2676
- * The manifest capability that announces the maintenance screen. The platform
2677
- * sets it where it keeps maintenance windows, and the administration offers the
2678
- * screen — and its lock banner — only where it is set.
2679
- */
2680
- declare const MAINTENANCE_CAPABILITY = "maintenance.manage";
2681
- /**
2682
- * What a tenant's page is told: nothing, a window ahead, or a lock. Dates are
2683
- * ISO strings, and `overrun` is the server's answer rather than the browser's,
2684
- * whose clock is not the one the window was announced by.
2685
- */
2686
- type MaintenanceStatusView = {
2687
- state: 'none';
2688
- } | {
2689
- state: 'announced';
2690
- startsAt: string;
2691
- endsAt: string;
2692
- message: string | null;
2693
- } | {
2694
- state: 'locked';
2695
- lockedAt: string;
2696
- /** The announced end; null where nobody said. */
2697
- endsAt: string | null;
2698
- message: string | null;
2699
- /** The announced end has passed, and the lock still holds. */
2700
- overrun: boolean;
2701
- };
2702
- /** A window as the administration shows it. */
2703
- interface MaintenanceWindowView {
2704
- id: string;
2705
- status: MaintenanceWindowStatus;
2706
- startsAt: string | null;
2707
- endsAt: string | null;
2708
- message: string | null;
2709
- createdAt: string;
2710
- createdBy: string;
2711
- lockedAt: string | null;
2712
- lockedBy: string | null;
2713
- endedAt: string | null;
2714
- endedBy: string | null;
2715
- /** Locked, and past its announced end. */
2716
- overrun: boolean;
2717
- /** Announced, never locked, and past its announced end: tenants no longer see it. */
2718
- lapsed: boolean;
2719
- }
2720
- /** `GET /admin/maintenance`: the open window, if any, and the ones before it. */
2721
- interface MaintenanceOverview {
2722
- open: MaintenanceWindowView | null;
2723
- /** Newest first, the open one included. */
2724
- recent: MaintenanceWindowView[];
2725
- /** How long a lock takes to reach every process. */
2726
- takesEffectWithinSeconds: number;
2727
- }
2728
- /** `POST /admin/maintenance/lock`: the locked window, and whether it was locked before. */
2729
- interface MaintenanceLockView {
2730
- window: MaintenanceWindowView;
2731
- /** The lock already held; nothing was changed. */
2732
- alreadyLocked: boolean;
2733
- /** How long the lock takes to reach every process. */
2734
- takesEffectWithinSeconds: number;
2735
- }
2736
- /** `POST /admin/maintenance/unlock`: the window it ended, or the open one it left alone. */
2737
- interface MaintenanceUnlockView {
2738
- window: MaintenanceWindowView | null;
2739
- /** Whether a lock held and was ended by this call. */
2740
- wasLocked: boolean;
2741
- }
2742
-
2743
- /** What the switch costs, per period of the subscriber's rhythm. */
2744
- interface RetirementSwitchTerms {
2745
- /** The replacement's net price. */
2746
- readonly priceNet: number;
2747
- /**
2748
- * Where the replacement costs more: the price the subscriber goes on paying,
2749
- * the difference that is held, and the last day it is held — the day before
2750
- * the date they were told. Null where it costs the same or less: its price
2751
- * then applies from the subscriber's next period.
2752
- */
2753
- readonly held: {
2754
- readonly priceNet: number;
2755
- readonly amountNet: number;
2756
- readonly lastDay: string;
2757
- } | null;
2758
- }
2759
- /**
2760
- * What switching to the replacement now costs in `billingCycle`, or null where
2761
- * the replacement has no price in it.
2762
- */
2763
- declare function retirementSwitchTerms(notice: Pick<VersionRetiredNotice, 'retired' | 'replacement' | 'lastDayToCancel'>, billingCycle: string): RetirementSwitchTerms | null;
2764
-
2765
- /** A version, as an announcement names it. */
2766
- interface RetiredVersionRef {
2767
- readonly planVersionId: string;
2768
- readonly planKey: string;
2769
- readonly version: number;
2770
- }
2771
- /** An announcement as it is kept: one per retirement, whoever it reaches. */
2772
- interface VersionRetirementRecord {
2773
- readonly id: string;
2774
- /** The version retired. */
2775
- readonly retired: RetiredVersionRef;
2776
- /** The version its subscriptions continue on, named by the operator. */
2777
- readonly replacement: RetiredVersionRef;
2778
- readonly announcedAt: Date;
2779
- /** Who announced it — an actor tag, as the audit log writes it. */
2780
- readonly announcedBy: string;
2781
- }
2782
- type NewVersionRetirement = Omit<VersionRetirementRecord, 'id'>;
2783
- /**
2784
- * The manifest capability that announces retiring a version. The platform sets
2785
- * it where it serves the routes, and the admin UI offers the action only where
2786
- * it is set. Whether the operator's terms allow it is a blocker the preview
2787
- * reports, so an operator who has not confirmed them learns what is missing.
2788
- */
2789
- declare const VERSION_RETIREMENT_CAPABILITY = "planVersions.retire";
2790
- /**
2791
- * One of the two versions of a retirement, as the subscriber compares them:
2792
- * price in each rhythm, quotas and features, with the plan it belongs to — the
2793
- * replacement may be a version of another plan.
2794
- */
2795
- interface RetirementSide extends VersionOfferSide {
2796
- readonly planKey: string;
2797
- }
2798
- /**
2799
- * A plan version a subscription is on is being retired, and the subscription
2800
- * continues on the named replacement from its effective date. Sent once per
2801
- * subscription and retirement, when the retirement is announced, and kept as
2802
- * it was sent: the record shows what the subscriber was told, prices included.
2803
- */
2804
- interface VersionRetiredNotice {
2805
- readonly kind: 'version-retired';
2806
- readonly tenantId: string;
2807
- readonly subscriptionId: string;
2808
- readonly retirementId: string;
2809
- readonly retired: RetirementSide;
2810
- readonly replacement: RetirementSide;
2811
- /** Every difference, retired to replacement, as the catalogue's diff states it. */
2812
- readonly changes: readonly VersionChange[];
2813
- /**
2814
- * The rhythm the subscription is billed in when the retirement takes
2815
- * effect — a change of rhythm scheduled by then included — which says
2816
- * which of the two prices applies.
2817
- */
2818
- readonly billingCycle: string;
2819
- /** ISO 8601. */
2820
- readonly effectiveAt: string;
2821
- /** ISO date (`YYYY-MM-DD`), UTC. */
2822
- readonly lastDayToCancel: string;
2823
- }
3104
+ };
3105
+ /** The longest message a window carries; the operator's words, not a document. */
3106
+ declare const MAINTENANCE_MESSAGE_MAX_LENGTH = 500;
2824
3107
  /**
2825
- * The one reminder of a retirement, where staying put costs the subscription
2826
- * something (`SC-SUB-034`): sent 14 days before the retirement takes effect,
2827
- * once per subscription and retired version. It says again what the
2828
- * retirement notice said, and what a switch taken now would cost. Its
2829
- * `billingCycle` is still the rhythm billed at the date, read again from the
2830
- * subscription as it stands when the reminder is sent: a change of rhythm
2831
- * scheduled since the announcement is in it.
3108
+ * How long a process may go on reading a lock state it read before. Every
3109
+ * request asks, so each process keeps the answer this long rather than asking
3110
+ * the database per request; the command that locks waits this long before it
3111
+ * returns, so that every process has seen the lock by then.
3112
+ *
3113
+ * Part of the contract between two versions of an application: the command
3114
+ * that locks comes from the release being deployed, while the processes it
3115
+ * waits for may still run the one before. It is safe only while the figure it
3116
+ * waits by is at least theirs, so a later release may raise it and never lower
3117
+ * it.
2832
3118
  */
2833
- interface VersionRetirementReminder extends Omit<VersionRetiredNotice, 'kind'> {
2834
- readonly kind: 'version-retirement-reminder';
2835
- /**
2836
- * What switching to the replacement now costs in the subscription's rhythm
2837
- * (`SC-SUB-032`), or null where it cannot switch now: in a trial, with a
2838
- * change scheduled, or where either plan is held for a special contract.
2839
- */
2840
- readonly switchTerms: RetirementSwitchTerms | null;
2841
- }
3119
+ declare const MAINTENANCE_STATE_MAX_AGE_SECONDS = 5;
2842
3120
  /**
2843
- * Why a retirement does not reach a subscription on the version:
2844
- *
2845
- * - `ended` — the subscription is over.
2846
- * - `cancelled-before` — its cancellation lands by the effective date.
2847
- * - `changes-before` — a scheduled change moves it to another plan, or to
2848
- * another version of this one, by then.
2849
- * - `no-term` — it carries no date a term can be counted from.
2850
- * - `already-told` — an earlier announcement of this version reached it, and
2851
- * stands.
3121
+ * The manifest capability that announces the maintenance screen. The platform
3122
+ * sets it where it keeps maintenance windows, and the administration offers the
3123
+ * screen — and its lock banner — only where it is set.
2852
3124
  */
2853
- type RetirementSkipReason = 'ended' | 'cancelled-before' | 'changes-before' | 'no-term' | 'already-told';
2854
- /** A refusal as the preview reports it and the announcement throws it. */
2855
- interface RetirementBlocker {
2856
- readonly code: string;
2857
- readonly message: string;
2858
- readonly params: Record<string, string | number>;
2859
- }
2860
- /** A subscription a retirement reaches, with what it means there. */
2861
- interface RetirementReachedRow {
2862
- readonly tenantId: string;
2863
- readonly subscriptionId: string;
2864
- readonly status: string;
2865
- /** The rhythm it is billed in when the retirement takes effect. */
2866
- readonly billingCycle: string;
2867
- /** ISO 8601. */
2868
- readonly effectiveAt: string;
2869
- /** ISO date, UTC. */
2870
- readonly lastDayToCancel: string;
2871
- /** Reached by another retirement within the last twelve months: the announcement waits. */
2872
- readonly reachedRecently: boolean;
3125
+ declare const MAINTENANCE_CAPABILITY = "maintenance.manage";
3126
+ /**
3127
+ * What a tenant's page is told: nothing, a window ahead, or a lock. Dates are
3128
+ * ISO strings, and `overrun` is the server's answer rather than the browser's,
3129
+ * whose clock is not the one the window was announced by.
3130
+ */
3131
+ type MaintenanceStatusView = {
3132
+ state: 'none';
3133
+ } | {
3134
+ state: 'announced';
3135
+ startsAt: string;
3136
+ endsAt: string;
3137
+ message: string | null;
3138
+ } | {
3139
+ state: 'locked';
3140
+ lockedAt: string;
3141
+ /** The announced end; null where nobody said. */
3142
+ endsAt: string | null;
3143
+ message: string | null;
3144
+ /** The announced end has passed, and the lock still holds. */
3145
+ overrun: boolean;
3146
+ };
3147
+ /** A window as the administration shows it. */
3148
+ interface MaintenanceWindowView {
3149
+ id: string;
3150
+ status: MaintenanceWindowStatus;
3151
+ startsAt: string | null;
3152
+ endsAt: string | null;
3153
+ message: string | null;
3154
+ createdAt: string;
3155
+ createdBy: string;
3156
+ lockedAt: string | null;
3157
+ lockedBy: string | null;
3158
+ endedAt: string | null;
3159
+ endedBy: string | null;
3160
+ /** Locked, and past its announced end. */
3161
+ overrun: boolean;
3162
+ /** Announced, never locked, and past its announced end: tenants no longer see it. */
3163
+ lapsed: boolean;
2873
3164
  }
2874
- /** A subscription on the version a retirement does not reach, and why. */
2875
- interface RetirementSkippedRow {
2876
- readonly tenantId: string;
2877
- readonly subscriptionId: string;
2878
- readonly reason: RetirementSkipReason;
3165
+ /** `GET /admin/maintenance`: the open window, if any, and the ones before it. */
3166
+ interface MaintenanceOverview {
3167
+ open: MaintenanceWindowView | null;
3168
+ /** Newest first, the open one included. */
3169
+ recent: MaintenanceWindowView[];
3170
+ /** How long a lock takes to reach every process. */
3171
+ takesEffectWithinSeconds: number;
2879
3172
  }
2880
- /** What announcing a retirement now would do. */
2881
- interface RetirementPreview {
2882
- readonly retired: RetirementSide;
2883
- readonly replacement: RetirementSide;
2884
- /** Every difference, retired to replacement, as the subscribers will be told it. */
2885
- readonly changes: readonly VersionChange[];
2886
- /** ISO 8601: the moment it is computed for. */
2887
- readonly asOf: string;
2888
- readonly reached: readonly RetirementReachedRow[];
2889
- readonly skipped: readonly RetirementSkippedRow[];
2890
- /** Empty where it may be announced as it stands. */
2891
- readonly blockers: readonly RetirementBlocker[];
3173
+ /** `POST /admin/maintenance/lock`: the locked window, and whether it was locked before. */
3174
+ interface MaintenanceLockView {
3175
+ window: MaintenanceWindowView;
3176
+ /** The lock already held; nothing was changed. */
3177
+ alreadyLocked: boolean;
3178
+ /** How long the lock takes to reach every process. */
3179
+ takesEffectWithinSeconds: number;
2892
3180
  }
2893
- /** What an announcement did. */
2894
- interface RetirementAnnounced {
2895
- readonly retirement: VersionRetirementRecord;
2896
- /** Notices sent now; the rest are sent by the next run. */
2897
- readonly told: number;
2898
- readonly failed: number;
3181
+ /** `POST /admin/maintenance/unlock`: the window it ended, or the open one it left alone. */
3182
+ interface MaintenanceUnlockView {
3183
+ window: MaintenanceWindowView | null;
3184
+ /** Whether a lock held and was ended by this call. */
3185
+ wasLocked: boolean;
2899
3186
  }
3187
+
2900
3188
  /**
2901
- * How far a retirement has come, counted over the subscriptions it reached
2902
- * (`SC-SUB-033`).
3189
+ * A newer version of a booked add-on, offered beside the booking: the version
3190
+ * booked and the one on sale side by side, what kind of offer it is, and when
3191
+ * a switch taken now would take effect — at once, or, for one that takes
3192
+ * something away, at the end of the booking's running term. The list of the
3193
+ * tenant's bookings carries it on each booking, as `offer`.
2903
3194
  */
2904
- interface RetirementProgress {
2905
- /** Off the retired version: moved at their date, switched early, or changed on their own. */
2906
- readonly moved: number;
2907
- /** Still on the retired version, before their date. */
2908
- readonly waiting: number;
2909
- /** Still on the retired version after their date: the run has not moved them yet, or cannot. */
2910
- readonly overdue: number;
2911
- /** Still on the retired version, and ended by their date: there is nothing to move. */
2912
- readonly ended: number;
2913
- /**
2914
- * Still on the retired version, and not told yet: their notice has reached
2915
- * nobody, so their date is not set and nothing moves them (`SC-SUB-036`).
2916
- */
2917
- readonly notTold: number;
2918
- /**
2919
- * Reminded 14 days before their date (`SC-SUB-034`) — counted beside the
2920
- * four above, not instead of one: a subscription reminded moves later.
2921
- */
2922
- readonly reminded: number;
2923
- }
2924
- /** An announcement as the administration lists it, with how far it has come. */
2925
- interface VersionRetirementView extends VersionRetirementRecord {
2926
- readonly progress: RetirementProgress;
2927
- }
2928
- /** What one run of the moves at the date did. */
2929
- interface RetirementMoveRun {
2930
- /** Subscriptions moved onto their replacement, with the contract the move writes. */
2931
- readonly moved: number;
2932
- /** Moves that could not be made, and are tried again by the next run. */
2933
- readonly failed: number;
3195
+ interface BundleVersionOfferView {
3196
+ readonly subscriptionBundleId: string;
3197
+ /** The plan both versions are priced beside: the one the subscription is on. */
3198
+ readonly planKey: string;
3199
+ /** The rhythm the booking is billed in, which the kind of offer is judged in. */
3200
+ readonly billingCycle: BillingCycle;
3201
+ readonly bound: BundleVersionSide;
3202
+ readonly offered: BundleVersionSide;
3203
+ readonly class: Exclude<VersionOfferClass, 'same'>;
3204
+ /** Every difference, bound to offered, with the price in the booking's rhythm alone. */
3205
+ readonly changes: readonly VersionChange[];
3206
+ /** ISO instant. */
3207
+ readonly takesEffectAt: string;
2934
3208
  }
2935
- /** What switching to the replacement before the date did (`SC-SUB-032`). */
2936
- interface RetirementSwitchResult {
2937
- readonly fromPlanVersionId: string;
2938
- readonly planVersionId: string;
2939
- /** ISO date of the last day the price is held, or null where none is. */
2940
- readonly heldUntilDay: string | null;
3209
+ /**
3210
+ * What taking an add-on offer did: the booking, the version left and the one
3211
+ * taken, and whether it applied at once or waits for `takesEffectAt`.
3212
+ */
3213
+ interface BundleVersionSwitchResult {
3214
+ readonly class: Exclude<VersionOfferClass, 'same'>;
3215
+ readonly subscriptionBundleId: string;
3216
+ readonly fromBundleVersionId: string;
3217
+ readonly bundleVersionId: string;
3218
+ readonly immediate: boolean;
3219
+ /** ISO instant. */
3220
+ readonly takesEffectAt: string;
2941
3221
  }
2942
3222
 
2943
3223
  /** What a notice is about. */
2944
- type SubscriptionNoticeKind = 'version-offered' | 'version-retired' | 'version-retirement-reminder';
3224
+ type SubscriptionNoticeKind = 'version-offered' | 'version-retired' | 'version-retirement-reminder' | 'bundle-version-retired' | 'bundle-version-retirement-reminder' | 'bundle-version-offered';
2945
3225
  /** Which notice: there is one per subscription, kind and subject. */
2946
3226
  interface SubscriptionNoticeKey {
2947
3227
  readonly tenantId: string;
@@ -2953,7 +3233,13 @@ interface SubscriptionNoticeKey {
2953
3233
  * is told of a version's retirement once, whichever announcement it came
2954
3234
  * with. The announcement is in the notice as `retirementId`. For
2955
3235
  * `version-retirement-reminder`, the id of the version retired as well: a
2956
- * subscription is reminded of a version's retirement once.
3236
+ * subscription is reminded of a version's retirement once. For
3237
+ * `bundle-version-retired`, the id of the add-on version retired: a
3238
+ * subscription holds one booking of an add-on, so that booking is told of
3239
+ * the retirement once. For `bundle-version-retirement-reminder`, the id of
3240
+ * the add-on version retired as well: that booking is reminded of it once.
3241
+ * For `bundle-version-offered`, the id of the add-on version offered: that
3242
+ * booking is told of the version once.
2957
3243
  */
2958
3244
  readonly subject: string;
2959
3245
  }
@@ -2992,8 +3278,21 @@ interface VersionOfferedNotice {
2992
3278
  /** The offer as `GET billing/version-offer` answers it at the moment the notice is due. */
2993
3279
  readonly offer: VersionOfferView;
2994
3280
  }
3281
+ /**
3282
+ * A newer version of an add-on a booking is on is now offered to it. Sent once
3283
+ * per booking and version, when the offer appears beside the add-on — the
3284
+ * notice and the offer say the same thing.
3285
+ */
3286
+ interface BundleVersionOfferedNotice {
3287
+ readonly kind: 'bundle-version-offered';
3288
+ readonly tenantId: string;
3289
+ readonly subscriptionId: string;
3290
+ readonly subscriptionBundleId: string;
3291
+ /** The offer as the list of the tenant's bookings shows it at the moment the notice is due. */
3292
+ readonly offer: BundleVersionOfferView;
3293
+ }
2995
3294
  /** A notice handed to the application to send. */
2996
- type SubscriptionNotice = VersionOfferedNotice | VersionRetiredNotice | VersionRetirementReminder;
3295
+ type SubscriptionNotice = VersionOfferedNotice | VersionRetiredNotice | VersionRetirementReminder | BundleVersionRetiredNotice | BundleVersionRetirementReminder | BundleVersionOfferedNotice;
2997
3296
 
2998
3297
  /**
2999
3298
  * A `subscription_notices` row as either adapter reads it back. The two JSON
@@ -3077,6 +3376,21 @@ interface CanonicalVersionRetirementRow {
3077
3376
  /** Reads a row back as a record, naming each column rather than spreading the row. */
3078
3377
  declare function toVersionRetirementRecord(row: CanonicalVersionRetirementRow): VersionRetirementRecord;
3079
3378
 
3379
+ /** A `bundle_version_retirements` row as either adapter reads it back. */
3380
+ interface CanonicalBundleVersionRetirementRow {
3381
+ id: string;
3382
+ retiredBundleVersionId: string;
3383
+ retiredBundleKey: string;
3384
+ retiredVersion: number;
3385
+ replacementBundleVersionId: string;
3386
+ replacementBundleKey: string;
3387
+ replacementVersion: number;
3388
+ announcedAt: Date;
3389
+ announcedBy: string;
3390
+ }
3391
+ /** Reads a row back as a record, naming each column rather than spreading the row. */
3392
+ declare function toBundleVersionRetirementRecord(row: CanonicalBundleVersionRetirementRow): BundleVersionRetirementRecord;
3393
+
3080
3394
  /** A scheduled change as a subscription row holds it. */
3081
3395
  interface ScheduledChangeColumns {
3082
3396
  readonly pendingPlan: string | null;
@@ -3119,9 +3433,15 @@ declare function retirementReminderIsDue(notice: Pick<VersionRetiredNotice, 'eff
3119
3433
  * Whether staying put costs the subscription something when the retirement
3120
3434
  * takes effect (D9): the replacement takes a feature or a quota away, or is
3121
3435
  * dearer in `billingCycle`, the rhythm it is billed in then — or not sold in
3122
- * it. A price that rises only in another rhythm costs it nothing.
3436
+ * it. A price that rises only in another rhythm costs it nothing. A plan
3437
+ * version's retirement and an add-on version's are judged alike.
3123
3438
  */
3124
- declare function retirementCostsTheSubscription(notice: Pick<VersionRetiredNotice, 'retired' | 'replacement' | 'changes' | 'lastDayToCancel'>, billingCycle: string): boolean;
3439
+ declare function retirementCostsTheSubscription(notice: {
3440
+ readonly retired: RetirementPricedSide;
3441
+ readonly replacement: RetirementPricedSide;
3442
+ readonly changes: readonly VersionChange[];
3443
+ readonly lastDayToCancel: string;
3444
+ }, billingCycle: string): boolean;
3125
3445
 
3126
3446
  /** A `maintenance_windows` row as either adapter reads it back. */
3127
3447
  type CanonicalMaintenanceWindowRow = MaintenanceWindowRecord;
@@ -3928,31 +4248,191 @@ interface PromoCodeValidationLogRepository {
3928
4248
  countValid(promoCodeId: string): Promise<number>;
3929
4249
  }
3930
4250
  /**
3931
- * First-time-customer check for the `firstTimeCustomersOnly` eligibility.
3932
- * The consumer implementation decides what "first time" means. Important:
3933
- * unfinished onboarding drafts must not count as an existing customer.
4251
+ * First-time-customer check for the `firstTimeCustomersOnly` eligibility.
4252
+ * The consumer implementation decides what "first time" means. Important:
4253
+ * unfinished onboarding drafts must not count as an existing customer.
4254
+ */
4255
+ interface FirstTimeCustomerCheck {
4256
+ /** Returns true if a completed/historical customer already exists for the email. */
4257
+ hasExistingCustomerForEmail(email: string): Promise<boolean>;
4258
+ }
4259
+ /** Subscription lookup for `redeem()`. Sufficient for promo calculations. */
4260
+ interface PromoSubscriptionLookup {
4261
+ findById(subscriptionId: string, tx?: TransactionContext): Promise<{
4262
+ id: string;
4263
+ tenantId: string;
4264
+ plan: string;
4265
+ billingCycle: BillingCycle;
4266
+ startedAt: Date | null;
4267
+ } | null>;
4268
+ }
4269
+ /**
4270
+ * Aggregation adapter for the stats endpoint (`PromoCodesService.stats`).
4271
+ * Consumers without an `InvoiceDiscount` table return '0.00'.
4272
+ */
4273
+ interface PromoRevenueDeductionAggregator {
4274
+ /** Sum of the amountGross values for all redemptions of a promo code (Decimal-as-string). */
4275
+ sumGrossForPromoCode(promoCodeId: string): Promise<string>;
4276
+ }
4277
+
4278
+ /** The adapter that gave an answer, recorded beside the answer. */
4279
+ interface TaxAdapterIdentity {
4280
+ /** The adapter's package name, such as `@saasicat/tax-de`. */
4281
+ name: string;
4282
+ /** The adapter's version as published, such as `1.0.0`. */
4283
+ version: string;
4284
+ }
4285
+ /** The kinds of tax treatment every adapter shares, in the order they are named. */
4286
+ declare const TAX_TREATMENT_KINDS: readonly ["standard", "reduced", "exempt", "reverse-charge", "not-taxable", "small-business"];
4287
+ /**
4288
+ * What a tax treatment is, in the words every adapter shares.
4289
+ *
4290
+ * - `standard` and `reduced`: the issuer's country taxes the charge at a rate.
4291
+ * - `exempt`: the charge is exempt in the issuer's country.
4292
+ * - `reverse-charge`: the subscriber, a business in another country, owes the
4293
+ * tax instead of the issuer.
4294
+ * - `not-taxable`: the charge is not taxable in the issuer's country at all,
4295
+ * such as a service to a business outside the European Union.
4296
+ * - `small-business`: the issuer charges no tax under a small business scheme.
4297
+ */
4298
+ type TaxTreatmentKind = (typeof TAX_TREATMENT_KINDS)[number];
4299
+ /** The treatment an adapter decided, as a contract and an invoice record it. */
4300
+ interface TaxTreatment {
4301
+ kind: TaxTreatmentKind;
4302
+ /** The rate in percent, such as `19`; `0` for every kind that charges no tax. */
4303
+ rate: number;
4304
+ /**
4305
+ * The sentence the document has to carry for this treatment, such as the
4306
+ * reference to the reverse charge; `null` where the law asks for none.
4307
+ */
4308
+ note: string | null;
4309
+ /** Who decided it. */
4310
+ adapter: TaxAdapterIdentity;
4311
+ }
4312
+ /**
4313
+ * Where a subscriber stands for tax purposes, as its record stands: what an
4314
+ * adapter decides a treatment from.
4315
+ */
4316
+ interface SubscriberTaxOrigin {
4317
+ /** The country of the billing address, ISO 3166-1 alpha-2; `null` while unknown. */
4318
+ country: string | null;
4319
+ /**
4320
+ * Whether the subscriber is a business, as sign-up or the operator recorded
4321
+ * it; `null` while nobody has said. Never derived from a tax identifier: a
4322
+ * business outside the European Union may have none.
4323
+ */
4324
+ business: boolean | null;
4325
+ /** The VAT identification number as entered, validated or not. */
4326
+ vatId: string | null;
4327
+ /**
4328
+ * The same number, only when its latest completed check found it valid;
4329
+ * otherwise `null`. An adapter decides as though a subscriber whose number
4330
+ * is not validated had none (`SC-PRIC-040`).
4331
+ */
4332
+ validatedVatId: string | null;
4333
+ }
4334
+ /** The issuer as an adapter needs it: the operator, as `config/saas.yaml` names it. */
4335
+ interface TaxIssuer {
4336
+ /** ISO 3166-1 alpha-2; `null` where the configuration names none. */
4337
+ country: string | null;
4338
+ vatId: string | null;
4339
+ }
4340
+ /** What an adapter decides a treatment for. */
4341
+ interface TaxDecisionRequest {
4342
+ issuer: TaxIssuer;
4343
+ origin: SubscriberTaxOrigin;
4344
+ /**
4345
+ * The period the charge covers, as a charge records it: from `from` up to
4346
+ * `until`, which is the first moment after it. A rate that changed in
4347
+ * between is the adapter's to see.
4348
+ */
4349
+ period: {
4350
+ from: Date;
4351
+ until: Date;
4352
+ };
4353
+ /**
4354
+ * The installation's time zone, an IANA name such as `Europe/Berlin`: the
4355
+ * calendar in which the days of the period count (`SC-PRIC-045`).
4356
+ */
4357
+ timeZone: string;
4358
+ }
4359
+ /**
4360
+ * An adapter's answer: a treatment, or a sentence saying the case is not
4361
+ * supported. An unsupported case is refused before a contract exists rather
4362
+ * than invoiced with a guessed tax (`SC-PRIC-039`).
4363
+ */
4364
+ type TaxDecision = {
4365
+ supported: true;
4366
+ treatment: TaxTreatment;
4367
+ } | {
4368
+ supported: false;
4369
+ reason: string;
4370
+ };
4371
+ /**
4372
+ * A completed check of a VAT identification number, with its date and what
4373
+ * the service returned (`SC-PRIC-040`). Every check is recorded for the
4374
+ * subscriber and never rewritten: a reverse charge rests on the confirmation
4375
+ * that held when the invoice was issued, and neither a later check nor a
4376
+ * corrected number may take it away.
3934
4377
  */
3935
- interface FirstTimeCustomerCheck {
3936
- /** Returns true if a completed/historical customer already exists for the email. */
3937
- hasExistingCustomerForEmail(email: string): Promise<boolean>;
4378
+ interface VatIdCheck {
4379
+ /** The number checked, exactly as it was stored when the check ran. */
4380
+ vatId: string;
4381
+ /**
4382
+ * When the service's answer was received, by the platform's clock, to the
4383
+ * millisecond. `keepsVatIdCheck` makes the check with the latest one count,
4384
+ * so a date of day precision — such as the request date VIES returns —
4385
+ * would make two checks of one day tie, and a date in the future would hold
4386
+ * back every check after it. Such a date belongs in `confirmation`.
4387
+ */
4388
+ checkedAt: Date;
4389
+ /** Whether the service confirmed the number as valid. */
4390
+ valid: boolean;
4391
+ /** The service that answered, such as `VIES`. */
4392
+ service: string;
4393
+ /**
4394
+ * What the service returned as its confirmation — a request identifier, the
4395
+ * name and address it holds for the number — as text, as the service sent it.
4396
+ */
4397
+ confirmation: Record<string, string>;
3938
4398
  }
3939
- /** Subscription lookup for `redeem()`. Sufficient for promo calculations. */
3940
- interface PromoSubscriptionLookup {
3941
- findById(subscriptionId: string, tx?: TransactionContext): Promise<{
3942
- id: string;
3943
- tenantId: string;
3944
- plan: string;
3945
- billingCycle: BillingCycle;
3946
- startedAt: Date | null;
3947
- } | null>;
4399
+ /**
4400
+ * How a check ended. A check that could not complete, such as while the
4401
+ * service is unavailable, is not a result: it leaves the number unvalidated
4402
+ * and is never read as valid.
4403
+ */
4404
+ type VatIdCheckOutcome = {
4405
+ completed: true;
4406
+ check: VatIdCheck;
4407
+ } | {
4408
+ completed: false;
4409
+ reason: string;
4410
+ };
4411
+ /**
4412
+ * How an application binds a tax adapter, the way it binds a payment gateway:
4413
+ * the adapter's name, which `config/saas.yaml#tax.adapter` names, and how to
4414
+ * build it from the options the file gives it. The options come from the file,
4415
+ * so the factory checks them and throws for one the adapter cannot take.
4416
+ */
4417
+ interface TaxAdapterFactory {
4418
+ /** The adapter's package name, such as `@saasicat/tax-de`. */
4419
+ readonly adapterName: string;
4420
+ create(options: Readonly<Record<string, unknown>>): TaxAdapter;
3948
4421
  }
3949
4422
  /**
3950
- * Aggregation adapter for the stats endpoint (`PromoCodesService.stats`).
3951
- * Consumers without an `InvoiceDiscount` table return '0.00'.
4423
+ * The tax adapter of an installation: a package for the country of its issuer,
4424
+ * named in `config/saas.yaml`. An adapter is a template, not tax advice; its
4425
+ * documentation says what it decides and on which basis.
3952
4426
  */
3953
- interface PromoRevenueDeductionAggregator {
3954
- /** Sum of the amountGross values for all redemptions of a promo code (Decimal-as-string). */
3955
- sumGrossForPromoCode(promoCodeId: string): Promise<string>;
4427
+ interface TaxAdapter extends TaxAdapterIdentity {
4428
+ /** The treatment of a charge, or why the case is not supported. Decides only; writes nothing. */
4429
+ decide(request: TaxDecisionRequest): TaxDecision;
4430
+ /**
4431
+ * Checks a VAT identification number with the service the adapter names.
4432
+ * Resolves to an outcome whatever the service does: an error, a timeout and
4433
+ * an answer the adapter cannot read are each a check that did not complete.
4434
+ */
4435
+ checkVatId(vatId: string, issuer: TaxIssuer): Promise<VatIdCheckOutcome>;
3956
4436
  }
3957
4437
 
3958
4438
  type ContractLineItemKind = 'plan' | 'bundle' | 'discount';
@@ -4070,6 +4550,14 @@ interface SubscriptionContractRecord extends SubscriptionContractParties {
4070
4550
  * never presented as what was agreed.
4071
4551
  */
4072
4552
  partiesMigrated: boolean;
4553
+ /**
4554
+ * The tax treatment the installation's tax adapter decided when the
4555
+ * contract was concluded, with the adapter's name and version
4556
+ * (`SC-PRIC-038`). `null` for a contract concluded without an adapter,
4557
+ * before one existed, or by a path that does not ask one yet; each invoice
4558
+ * then takes the adapter's answer when it is issued.
4559
+ */
4560
+ taxTreatment: TaxTreatment | null;
4073
4561
  status: SubscriptionContractStatus;
4074
4562
  effectiveFrom: Date;
4075
4563
  effectiveUntil: Date | null;
@@ -4116,6 +4604,11 @@ interface NewSubscriptionContractData extends CreateSubscriptionContractData {
4116
4604
  * means `false`.
4117
4605
  */
4118
4606
  partiesMigrated?: boolean;
4607
+ /**
4608
+ * The treatment the platform had the tax adapter decide, recorded as it
4609
+ * was answered and never rewritten. Absent means `null`.
4610
+ */
4611
+ taxTreatment?: TaxTreatment | null;
4119
4612
  }
4120
4613
  interface TerminateSubscriptionContractData {
4121
4614
  /**
@@ -4224,16 +4717,115 @@ interface SubscriberContact extends PartyAddress {
4224
4717
  /** Where invoices will be sent. */
4225
4718
  invoiceEmail: string | null;
4226
4719
  }
4720
+ /**
4721
+ * Whether the subscriber is a business: part of its tax origin beside the
4722
+ * country and the VAT identification number (ADR 0013).
4723
+ */
4724
+ interface SubscriberTaxStatus {
4725
+ /**
4726
+ * As sign-up or the operator recorded it; `null` while nobody has said.
4727
+ * Never derived from a tax identifier: a business outside the European
4728
+ * Union may have none, and is still a business.
4729
+ */
4730
+ business: boolean | null;
4731
+ }
4732
+ /**
4733
+ * The address an invoice names. Sign-up asks for every one of them, and once
4734
+ * given they can be changed but not cleared: without them nothing can be
4735
+ * invoiced (`SC-PRIC-032`).
4736
+ */
4737
+ declare const SUBSCRIBER_INVOICE_ADDRESS_FIELDS: readonly ["addressLine1", "postalCode", "city", "country"];
4738
+ type SubscriberInvoiceAddressField = (typeof SUBSCRIBER_INVOICE_ADDRESS_FIELDS)[number];
4739
+ /**
4740
+ * Whether a subscriber can be given its next contract where a tax adapter
4741
+ * decides (`SC-PRIC-032`, `SC-PRIC-039`): which fields of the address an
4742
+ * invoice names are empty, and the adapter's sentence where it supports no
4743
+ * treatment for the subscriber as it stands. Computed when it is read, from the
4744
+ * record and the adapter as they are then.
4745
+ */
4746
+ interface SubscriberReadiness {
4747
+ ready: boolean;
4748
+ missing: SubscriberInvoiceAddressField[];
4749
+ /** The adapter's sentence, or `null` where it treats the subscriber. */
4750
+ taxRefusal: string | null;
4751
+ }
4752
+ /**
4753
+ * A tenant's subscriber as the operator sees it beside the tenant: who the
4754
+ * contracts are concluded with, what a tax adapter decides from, and — where
4755
+ * one decides — what holds its next contract back (`SC-PRIC-070`).
4756
+ */
4757
+ interface AdminTenantSubscriber {
4758
+ subscriber: {
4759
+ id: string;
4760
+ customerNumber: string;
4761
+ legalName: string;
4762
+ addressLine1: string | null;
4763
+ addressLine2: string | null;
4764
+ postalCode: string | null;
4765
+ city: string | null;
4766
+ country: string | null;
4767
+ business: boolean | null;
4768
+ vatId: string | null;
4769
+ /** Whether the check that counts for the VAT id found it valid. */
4770
+ vatIdValidated: boolean;
4771
+ taxNumber: string | null;
4772
+ /** Created from the application's own tenant record, not from what a customer entered. */
4773
+ migrated: boolean;
4774
+ } | null;
4775
+ /** `null` where no tax adapter decides, or the tenant has no subscriber. */
4776
+ readiness: SubscriberReadiness | null;
4777
+ }
4778
+ /**
4779
+ * The manifest capability that announces the operator's view of a tenant's
4780
+ * subscriber. The platform sets it where it serves the view.
4781
+ */
4782
+ declare const SUBSCRIBER_STANDING_CAPABILITY = "subscribers.read";
4783
+ /**
4784
+ * The manifest capability that says a tax adapter decides, so a subscriber can
4785
+ * be held back from its next contract: the operator's lists ask which only
4786
+ * where it is set, and are spared the question everywhere else.
4787
+ */
4788
+ declare const SUBSCRIBER_ATTENTION_CAPABILITY = "subscribers.attention";
4789
+ /**
4790
+ * How many tenants one question about attention may name: a page of a list,
4791
+ * not the whole of it. A list longer than this asks in pages.
4792
+ */
4793
+ declare const SUBSCRIBER_ATTENTION_PAGE_SIZE = 200;
4794
+ /**
4795
+ * The manifest capability that announces the operator's corrections of a
4796
+ * subscriber — its legal identity, its business status, a check of its VAT
4797
+ * identification number — beside the subscriber's view.
4798
+ */
4799
+ declare const SUBSCRIBER_CORRECTION_CAPABILITY = "subscribers.correct";
4800
+ /** A tenant whose subscriber cannot be given its next contract, and why. */
4801
+ interface AdminSubscriberAttention {
4802
+ tenantId: string;
4803
+ readiness: SubscriberReadiness;
4804
+ }
4805
+ /** A live subscriber with the check of its VAT id that counts now. */
4806
+ interface SubscriberWithCurrentCheck {
4807
+ subscriber: SubscriberRecord;
4808
+ currentVatIdCheck: SubscriberVatIdCheckRecord | null;
4809
+ }
4227
4810
  /** A subscriber's master data, as it stands. */
4228
- type SubscriberDetails = LegalIdentity & SubscriberContact;
4811
+ type SubscriberDetails = LegalIdentity & SubscriberContact & SubscriberTaxStatus;
4229
4812
  /**
4230
4813
  * What a subscriber is created with.
4231
4814
  *
4232
- * Only the legal name is required. The address, the tax identifiers and the
4233
- * invoice email stay optional until sign-up asks for them and invoicing
4234
- * requires them; an absent or blank value is recorded as unknown.
4815
+ * Only the legal name is required. The address, the tax identifiers, the
4816
+ * business status and the invoice email stay optional until sign-up asks for
4817
+ * them and invoicing requires them; an absent or blank value is recorded as
4818
+ * unknown.
4235
4819
  */
4236
- type NewSubscriberDetails = Pick<SubscriberDetails, 'legalName'> & Partial<Omit<SubscriberDetails, 'legalName'>>;
4820
+ type NewSubscriberDetails = Pick<SubscriberDetails, 'legalName'> & Partial<Omit<SubscriberDetails, 'legalName'>> & {
4821
+ /**
4822
+ * A check of `vatId` made before the subscriber existed — in a
4823
+ * sign-up's step 4, or by `SubscriberService.assessNewSubscriber` —
4824
+ * recorded with it when it is created, so its first contract is
4825
+ * decided from it. A check of another number is refused.
4826
+ */
4827
+ vatIdCheck?: VatIdCheck | null;
4828
+ };
4237
4829
  interface SubscriberRecord extends SubscriberDetails {
4238
4830
  id: string;
4239
4831
  /**
@@ -4287,13 +4879,15 @@ interface SubscriberIdentityDelta {
4287
4879
  previous: SubscriberIdentityValues;
4288
4880
  corrected: SubscriberIdentityValues;
4289
4881
  }
4290
- /** What a repository writes for a correction the service has accepted. */
4882
+ /**
4883
+ * What a repository writes for a correction the service has accepted. The
4884
+ * repository dates it, while it holds the subscriber's row lock.
4885
+ */
4291
4886
  interface SubscriberCorrectionData {
4292
4887
  /** The new values; a field equal to what is stored is not recorded. */
4293
4888
  corrected: SubscriberIdentityValues;
4294
4889
  reason: string;
4295
4890
  correctedBy: string;
4296
- correctedAt: Date;
4297
4891
  }
4298
4892
  /** One correction of a subscriber's legal identity, as it was recorded. */
4299
4893
  interface SubscriberCorrectionRecord {
@@ -4305,6 +4899,12 @@ interface SubscriberCorrectionRecord {
4305
4899
  corrected: SubscriberIdentityValues;
4306
4900
  reason: string;
4307
4901
  correctedBy: string;
4902
+ /**
4903
+ * When the write that made it held the subscriber's row lock, by the
4904
+ * platform's clock. The list is in the order the database numbered the
4905
+ * writes; on one clock these dates follow that order, while two instances
4906
+ * whose clocks differ may date neighbouring corrections out of it.
4907
+ */
4308
4908
  correctedAt: Date;
4309
4909
  }
4310
4910
  /** The outcome of writing a correction: nothing is recorded when no value moved. */
@@ -4312,11 +4912,147 @@ interface SubscriberCorrectionResult {
4312
4912
  subscriber: SubscriberRecord;
4313
4913
  correction: SubscriberCorrectionRecord | null;
4314
4914
  }
4915
+ /**
4916
+ * The details a subscriber's tax origin consists of, and whose change is
4917
+ * recorded with its date — in the order they are named and shown.
4918
+ */
4919
+ declare const SUBSCRIBER_TAX_ORIGIN_FIELDS: readonly ["country", "business", "vatId"];
4920
+ type SubscriberTaxOriginField = (typeof SUBSCRIBER_TAX_ORIGIN_FIELDS)[number];
4921
+ /** Tax origin values by field, holding only the fields a change moved. */
4922
+ type SubscriberTaxOriginValues = Partial<Pick<SubscriberDetails, SubscriberTaxOriginField>>;
4923
+ /**
4924
+ * One change of a subscriber's tax origin, as it was recorded: written in the
4925
+ * same transaction as the change, whichever way it arrived — a contact change
4926
+ * of the country, a correction of the VAT identification number, a change of
4927
+ * the business status — and never rewritten. A change applies from the
4928
+ * subscriber's next invoice (`SC-PRIC-043`).
4929
+ */
4930
+ interface SubscriberTaxOriginChangeRecord {
4931
+ id: string;
4932
+ subscriberId: string;
4933
+ /** The values the change replaced. */
4934
+ previous: SubscriberTaxOriginValues;
4935
+ /** The values it wrote. */
4936
+ changed: SubscriberTaxOriginValues;
4937
+ /** Who changed it, as an actor tag the audit log would write. */
4938
+ changedBy: string;
4939
+ /**
4940
+ * When the write that made it held the subscriber's row lock, by the
4941
+ * platform's clock. The list is in the order the database numbered the
4942
+ * writes; on one clock these dates follow that order, while two instances
4943
+ * whose clocks differ may date neighbouring changes out of it.
4944
+ */
4945
+ changedAt: Date;
4946
+ /**
4947
+ * Why it was changed: the reason of the correction or of the change of
4948
+ * business status that made it; `null` for a change of the country, which
4949
+ * comes with the contact details and states none.
4950
+ */
4951
+ reason: string | null;
4952
+ }
4953
+ /** What a repository writes for a change of the business status the service has accepted. */
4954
+ interface SubscriberBusinessStatusData {
4955
+ business: boolean | null;
4956
+ /** Who changes it, as an actor tag the audit log would write. */
4957
+ changedBy: string;
4958
+ /** Why, in the operator's words: whether it is a business decides the tax treatment. */
4959
+ reason: string;
4960
+ }
4961
+ /** The outcome of writing a business status: nothing is recorded when it does not move. */
4962
+ interface SubscriberBusinessStatusResult {
4963
+ subscriber: SubscriberRecord;
4964
+ change: SubscriberTaxOriginChangeRecord | null;
4965
+ }
4966
+ /**
4967
+ * One completed check of a subscriber's VAT identification number, as it was
4968
+ * recorded: never rewritten, whether it counts now or not.
4969
+ */
4970
+ interface SubscriberVatIdCheckRecord extends VatIdCheck {
4971
+ id: string;
4972
+ subscriberId: string;
4973
+ /** When the check was recorded, by the platform's clock. */
4974
+ recordedAt: Date;
4975
+ }
4976
+ /** The outcome of recording a check: the check as recorded, and the one that counts now. */
4977
+ interface RecordedVatIdCheck {
4978
+ recorded: SubscriberVatIdCheckRecord;
4979
+ /**
4980
+ * The check that counts for the subscriber's number from now on: the one
4981
+ * just recorded, one recorded earlier that completed later, or none — a
4982
+ * check of a number the subscriber no longer has counts for nothing.
4983
+ */
4984
+ current: SubscriberVatIdCheckRecord | null;
4985
+ }
4986
+ /**
4987
+ * What became of a check of a subscriber's VAT identification number: the
4988
+ * check as it was recorded, and whether it counts for the number held — or why
4989
+ * it did not complete, in which case nothing was recorded and the number stays
4990
+ * as validated as it was (`SC-PRIC-040`).
4991
+ */
4992
+ type SubscriberVatIdCheckResult = {
4993
+ completed: true;
4994
+ check: SubscriberVatIdCheckRecord;
4995
+ counts: boolean;
4996
+ } | {
4997
+ completed: false;
4998
+ reason: string;
4999
+ };
5000
+ /** A check of a subscriber's VAT identification number, as the operator is shown it. */
5001
+ type AdminVatIdCheckOutcome = {
5002
+ completed: true;
5003
+ valid: boolean;
5004
+ /** When the service answered, as an ISO string. */
5005
+ checkedAt: string;
5006
+ service: string;
5007
+ /** Whether it is the check that counts for the number held now. */
5008
+ counts: boolean;
5009
+ } | {
5010
+ completed: false;
5011
+ reason: string;
5012
+ };
5013
+ /**
5014
+ * The answer to an operator's correction or check: the subscriber as it now
5015
+ * stands, and the check a VAT identification number got, where one was made.
5016
+ */
5017
+ interface AdminSubscriberCorrected {
5018
+ subscriber: AdminTenantSubscriber;
5019
+ vatIdCheck: AdminVatIdCheckOutcome | null;
5020
+ }
5021
+ /**
5022
+ * One entry of a subscriber's history as the operator reads it, the latest
5023
+ * first: a correction of its legal identity, a change of its country or
5024
+ * business status, or a check of its VAT identification number. Dates are ISO
5025
+ * strings.
5026
+ */
5027
+ type AdminSubscriberHistoryEntry = {
5028
+ kind: 'identity-corrected';
5029
+ at: string;
5030
+ by: string;
5031
+ previous: SubscriberIdentityValues;
5032
+ corrected: SubscriberIdentityValues;
5033
+ reason: string;
5034
+ } | {
5035
+ kind: 'tax-origin-changed';
5036
+ at: string;
5037
+ by: string;
5038
+ previous: SubscriberTaxOriginValues;
5039
+ changed: SubscriberTaxOriginValues;
5040
+ /** `null` for a change of the country with the contact details. */
5041
+ reason: string | null;
5042
+ } | {
5043
+ kind: 'vat-id-checked';
5044
+ at: string;
5045
+ vatId: string;
5046
+ valid: boolean;
5047
+ service: string;
5048
+ /** Whether it is the check that counts for the number held now. */
5049
+ counts: boolean;
5050
+ };
4315
5051
 
4316
5052
  /**
4317
- * 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.
5053
+ * 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. bundleChange: what an add-on's switch to a dearer version adds for the rest of its period. 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.
4318
5054
  */
4319
- type SubscriberChargeOrigin = 'activation' | 'renewal' | 'planChange' | 'bundleBooking' | 'credit' | 'correction';
5055
+ type SubscriberChargeOrigin = 'activation' | 'renewal' | 'planChange' | 'bundleBooking' | 'bundleChange' | 'credit' | 'correction';
4320
5056
  /**
4321
5057
  * Which kind of contract line the charge realises.
4322
5058
  */
@@ -4592,6 +5328,59 @@ interface SubscriptionBundleRepository {
4592
5328
  * implementations to avoid drift.
4593
5329
  */
4594
5330
  countActiveByBundleVersionId(bundleVersionId: string, asOf?: Date): Promise<number>;
5331
+ /**
5332
+ * Every booking of the add-on version `bundleVersionId`, in every tenant,
5333
+ * whatever its state. The platform reads it to find the bookings an add-on
5334
+ * retirement reaches, inside the RLS bypass, and decides itself which of
5335
+ * them are still running.
5336
+ *
5337
+ * Optional, so a repository written before it keeps working; retiring an
5338
+ * add-on version over one without it is refused at start-up.
5339
+ */
5340
+ listOfVersion?(bundleVersionId: string): Promise<SubscriptionBundleRecord[]>;
5341
+ /**
5342
+ * Moves the booking `subscriptionBundleId` from the add-on version `from`
5343
+ * onto `to` and answers it as it now stands, or null where it is not on
5344
+ * `from` any more, or gone. Nothing else changes: its period, its terms,
5345
+ * its rhythm and its cancellation stay as they are. Conditional on `from`,
5346
+ * so a move and the put-back of a move that could not write its contract
5347
+ * never write over each other, nor two runs over one booking.
5348
+ *
5349
+ * An add-on retirement moves a booking at its date, and a subscriber by
5350
+ * taking a newer version offered (`SC-BUN-058`). Optional, so a repository
5351
+ * written before it keeps working; retiring an add-on version over one
5352
+ * without it is refused at start-up, and no newer version is offered.
5353
+ */
5354
+ moveToVersion?(subscriptionBundleId: string, from: string, to: string): Promise<SubscriptionBundleRecord | null>;
5355
+ /**
5356
+ * Schedules the booking `subscriptionBundleId` to continue on the add-on
5357
+ * version `to` from `effectiveAt` — `pendingBundleVersionId` and
5358
+ * `pendingVersionEffectiveAt` — and answers it as it now stands, or null
5359
+ * where it is not on `from` any more, already has a switch scheduled, or is
5360
+ * gone. Nothing else changes, its version included: the switch is made at
5361
+ * that moment by the run (`listScheduledVersionsDue`).
5362
+ *
5363
+ * Optional, and so are the two methods after it: without all three, a
5364
+ * newer version that takes something away is not offered.
5365
+ */
5366
+ scheduleVersion?(subscriptionBundleId: string, switchTo: {
5367
+ from: string;
5368
+ to: string;
5369
+ effectiveAt: Date;
5370
+ }): Promise<SubscriptionBundleRecord | null>;
5371
+ /**
5372
+ * Clears the switch scheduled for the booking `subscriptionBundleId`, and
5373
+ * answers it as it now stands; null where no switch to `to` is scheduled
5374
+ * any more, or it is gone. Its version stays as it is.
5375
+ */
5376
+ unscheduleVersion?(subscriptionBundleId: string, to: string): Promise<SubscriptionBundleRecord | null>;
5377
+ /**
5378
+ * Every booking, in every tenant and whatever its state, with a switch
5379
+ * scheduled to take effect at or before `asOf` — oldest first. The
5380
+ * platform reads it inside the RLS bypass and decides itself which of
5381
+ * them still move.
5382
+ */
5383
+ listScheduledVersionsDue?(asOf: Date): Promise<SubscriptionBundleRecord[]>;
4595
5384
  }
4596
5385
  /**
4597
5386
  * Append-only repository for V3 SubscriptionContracts. Contracts are the
@@ -4694,19 +5483,66 @@ interface SubscriberRepository {
4694
5483
  findById(subscriberId: string, tx?: TransactionContext): Promise<SubscriberRecord | null>;
4695
5484
  /** The subscriber live for this tenant, or `null` when it has none. */
4696
5485
  findByTenantId(tenantId: string, tx?: TransactionContext): Promise<SubscriberRecord | null>;
4697
- /** Writes the members given and keeps the rest; `null` when no such subscriber exists. */
4698
- updateContact(subscriberId: string, change: SubscriberContactChange, tx?: TransactionContext): Promise<SubscriberRecord | null>;
5486
+ /**
5487
+ * Writes the members given and keeps the rest; `null` when no such
5488
+ * subscriber exists. Read and written under the lock a correction takes. A
5489
+ * change of the country is a change of the tax origin and is recorded as
5490
+ * one in the same step, by `changedBy` and dated while the lock is held.
5491
+ */
5492
+ updateContact(subscriberId: string, change: SubscriberContactChange, changedBy: string, tx?: TransactionContext): Promise<SubscriberRecord | null>;
4699
5493
  /**
4700
5494
  * Writes a correction of the legal identity and records it, in one step:
4701
5495
  * the subscriber is read and changed under a lock, so the values recorded
4702
5496
  * as replaced are the ones this write replaced even when two corrections
4703
- * arrive at once. A field whose stored value already equals the corrected
4704
- * one is left out of the record, and when none differs nothing is written
4705
- * and `correction` is `null`. `null` when no such subscriber exists.
5497
+ * arrive at once. The correction is dated while the lock is held and
5498
+ * numbered by the database as it is written. A field whose stored value
5499
+ * already equals the corrected one is left out of the record, and when none
5500
+ * differs nothing is written and `correction` is `null`. `null` when no
5501
+ * such subscriber exists.
5502
+ *
5503
+ * A corrected VAT identification number is a change of the tax origin and
5504
+ * is recorded as one too, by the same actor and with the same date.
5505
+ * The check that counted for the number it replaced counts no more — it
5506
+ * would otherwise validate that number again should it come back — and
5507
+ * stays recorded (`listVatIdChecks`); the number written is held from that
5508
+ * date (`vatIdSince`), so no check completed before it counts for it.
4706
5509
  */
4707
5510
  correctIdentity(subscriberId: string, data: SubscriberCorrectionData, tx?: TransactionContext): Promise<SubscriberCorrectionResult | null>;
4708
- /** Every correction of this subscriber, the latest first. */
5511
+ /** Every correction of this subscriber, the latest written first. */
4709
5512
  listCorrections(subscriberId: string): Promise<SubscriberCorrectionRecord[]>;
5513
+ /**
5514
+ * Writes whether the subscriber is a business and records the change of
5515
+ * its tax origin, in one step and under the same lock as a correction,
5516
+ * dated while the lock is held. When the stored status already equals the
5517
+ * one given nothing is written and `change` is `null`. `null` when no such
5518
+ * subscriber exists.
5519
+ */
5520
+ changeBusinessStatus(subscriberId: string, data: SubscriberBusinessStatusData, tx?: TransactionContext): Promise<SubscriberBusinessStatusResult | null>;
5521
+ /**
5522
+ * Records a completed check of the subscriber's VAT identification number.
5523
+ * Every check is recorded and none is rewritten or removed: it is the
5524
+ * evidence a reverse charge rests on. Under the lock a correction takes it
5525
+ * then decides whether the check counts from now on — only for the number
5526
+ * the subscriber holds, completed since it holds it, and never over a check
5527
+ * that completed later (`keepsVatIdCheck` from `@saasicat/core` decides).
5528
+ * `null` when no such subscriber exists.
5529
+ */
5530
+ recordVatIdCheck(subscriberId: string, check: VatIdCheck, tx?: TransactionContext): Promise<RecordedVatIdCheck | null>;
5531
+ /**
5532
+ * The check that counts for the subscriber's number now, or `null` while
5533
+ * none does: never checked, or corrected since.
5534
+ */
5535
+ findCurrentVatIdCheck(subscriberId: string, tx?: TransactionContext): Promise<SubscriberVatIdCheckRecord | null>;
5536
+ /** Every check recorded for this subscriber, counting or not, the latest checked first. */
5537
+ listVatIdChecks(subscriberId: string): Promise<SubscriberVatIdCheckRecord[]>;
5538
+ /**
5539
+ * The live subscribers of these tenants, each with the check of its VAT id
5540
+ * that counts now, in at most a few reads — what the operator's lists mark
5541
+ * a subscriber from. A tenant without a live subscriber is left out.
5542
+ */
5543
+ listForTenants(tenantIds: readonly string[], tx?: TransactionContext): Promise<SubscriberWithCurrentCheck[]>;
5544
+ /** Every recorded change of this subscriber's tax origin, the latest written first. */
5545
+ listTaxOriginChanges(subscriberId: string): Promise<SubscriberTaxOriginChangeRecord[]>;
4710
5546
  }
4711
5547
  /**
4712
5548
  * The subscriber's account: the charges that became due, one per contract line
@@ -4863,6 +5699,16 @@ interface SubscriptionUsagePort {
4863
5699
  * port without it is refused at start-up.
4864
5700
  */
4865
5701
  listBoundToVersion?(planVersionId: string): Promise<TenantSubscriptionUsage[]>;
5702
+ /**
5703
+ * The subscriptions `subscriptionIds`, in whichever tenant, each with the
5704
+ * tenant it belongs to; an id that names none is left out. The platform
5705
+ * reads it inside the RLS bypass to find the subscription of each booking
5706
+ * an add-on retirement reaches.
5707
+ *
5708
+ * Optional, so a port written before it keeps working; retiring an add-on
5709
+ * version over a port without it is refused at start-up.
5710
+ */
5711
+ listByIds?(subscriptionIds: readonly string[]): Promise<TenantSubscriptionUsage[]>;
4866
5712
  }
4867
5713
  /**
4868
5714
  * Returns the current usage for all quotaKeys of a tenant declared via
@@ -5336,7 +6182,9 @@ interface AdminUserListRow {
5336
6182
  }
5337
6183
  interface AdminSubscriptionListRow {
5338
6184
  id: string;
6185
+ /** The tenant by its id too: what the operator's lists ask a subscriber's standing by. */
5339
6186
  tenant: {
6187
+ id: string;
5340
6188
  slug: string;
5341
6189
  name: string;
5342
6190
  };
@@ -6221,13 +7069,28 @@ interface SubscriptionNoticeRepository {
6221
7069
  * Throw where it could not be sent and should be tried again: the claim is
6222
7070
  * released and the next run sends it. Resolving with no recipients records that
6223
7071
  * nobody could be told, and the notice is not tried again — except a
6224
- * retirement's notice (`version-retired`), which nobody was told of: it is tried
6225
- * again by every run until somebody is, and its date counts from then.
7072
+ * retirement's notice (`version-retired`, `bundle-version-retired`), which
7073
+ * nobody was told of: it is tried again by every run until somebody is, and its
7074
+ * date counts from then.
6226
7075
  */
6227
7076
  interface SubscriptionNoticePort {
6228
7077
  deliver(notice: SubscriptionNotice): Promise<SubscriptionNoticeDelivery>;
6229
7078
  }
6230
7079
 
7080
+ /**
7081
+ * Keeps every add-on retirement announcement: which version, which
7082
+ * replacement, when and by whom. What it means for each booking it reaches is
7083
+ * kept beside it as a notice of kind `bundle-version-retired`, written in the
7084
+ * same transaction.
7085
+ */
7086
+ interface BundleVersionRetirementRepository {
7087
+ /** Records an announcement, in the caller's transaction where one is given. */
7088
+ create(data: NewBundleVersionRetirement, tx?: TransactionContext): Promise<BundleVersionRetirementRecord>;
7089
+ /** Every announcement, the most recent first. */
7090
+ list(): Promise<BundleVersionRetirementRecord[]>;
7091
+ findById(id: string): Promise<BundleVersionRetirementRecord | null>;
7092
+ }
7093
+
6231
7094
  /**
6232
7095
  * Keeps every retirement announcement: which version, which replacement, when
6233
7096
  * and by whom. What it means for each subscription it reaches is kept beside it
@@ -6365,6 +7228,12 @@ interface SaaSiCatPersistenceTenantBilling {
6365
7228
  * retire versions without one is refused at start-up.
6366
7229
  */
6367
7230
  versionRetirements?: PersistenceProvider<VersionRetirementRepository>;
7231
+ /**
7232
+ * The record of every add-on retirement announcement. Optional so an
7233
+ * adapter written before it keeps working; without it, retiring an add-on
7234
+ * version is off, and retiring a plan version is not affected.
7235
+ */
7236
+ bundleVersionRetirements?: PersistenceProvider<BundleVersionRetirementRepository>;
6368
7237
  }
6369
7238
  /**
6370
7239
  * The record of payment gateway callbacks and the payment methods they confirm
@@ -6531,6 +7400,13 @@ declare const CATALOG_ERROR_CODES: {
6531
7400
  readonly PLAN_NOT_FOUND: "PLAN_NOT_FOUND";
6532
7401
  readonly PLAN_VERSION_NOT_FOUND: "PLAN_VERSION_NOT_FOUND";
6533
7402
  readonly BUNDLE_NOT_FOUND: "BUNDLE_NOT_FOUND";
7403
+ /**
7404
+ * Bookings told that their add-on version is being retired have still to
7405
+ * move onto a version of this add-on — waiting for their notice, for their
7406
+ * date, or past it — and a deleted add-on is booked by nothing, the move
7407
+ * included. Carries how many, and the add-on's key.
7408
+ */
7409
+ readonly BUNDLE_DELETE_WHILE_RETIREMENT_MOVES_PENDING: "BUNDLE_DELETE_WHILE_RETIREMENT_MOVES_PENDING";
6534
7410
  readonly BUNDLE_VERSION_NOT_FOUND: "BUNDLE_VERSION_NOT_FOUND";
6535
7411
  readonly FEATURE_NOT_FOUND: "FEATURE_NOT_FOUND";
6536
7412
  readonly QUOTA_NOT_FOUND: "QUOTA_NOT_FOUND";
@@ -6718,6 +7594,16 @@ declare const BILLING_ERROR_CODES: {
6718
7594
  * to pick, so the way past it is the add-on ending.
6719
7595
  */
6720
7596
  readonly RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW: "RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW";
7597
+ /**
7598
+ * As `RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW`, where only the version the
7599
+ * add-on continues on from a retirement's date cannot run beside the
7600
+ * replacement's plan. The version it is on can, so cancelling it — it then
7601
+ * ends before that date — lets the switch through. Given while that date
7602
+ * is ahead and the add-on is not cancelled yet; otherwise the earlier code
7603
+ * names the day it can end. Carries the add-on, that version, its date and
7604
+ * the plan.
7605
+ */
7606
+ readonly RETIREMENT_SWITCH_BUNDLE_REPLACEMENT_CANNOT_FOLLOW: "RETIREMENT_SWITCH_BUNDLE_REPLACEMENT_CANNOT_FOLLOW";
6721
7607
  /**
6722
7608
  * The subscription takes no switch now: a change is scheduled, it has
6723
7609
  * ended, or its plan is held for a special contract.
@@ -6728,6 +7614,69 @@ declare const BILLING_ERROR_CODES: {
6728
7614
  * the retirement as it now stands.
6729
7615
  */
6730
7616
  readonly RETIREMENT_SWITCH_CHANGED: "RETIREMENT_SWITCH_CHANGED";
7617
+ /**
7618
+ * The add-on version is still on sale: a booking made after the
7619
+ * announcement would be on it without having been told. Carries the
7620
+ * add-on key and the version.
7621
+ */
7622
+ readonly BUNDLE_RETIREMENT_VERSION_ON_SALE: "BUNDLE_RETIREMENT_VERSION_ON_SALE";
7623
+ /** The replacement is not on sale, so no booking can continue on it. Carries add-on key and version. */
7624
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_NOT_ON_SALE: "BUNDLE_RETIREMENT_REPLACEMENT_NOT_ON_SALE";
7625
+ /**
7626
+ * The replacement is a version of another add-on. A booking continues on
7627
+ * a version of its own add-on, so it stays the same booking with its term.
7628
+ * Carries both add-on keys.
7629
+ */
7630
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_OF_ANOTHER_BUNDLE: "BUNDLE_RETIREMENT_REPLACEMENT_OF_ANOTHER_BUNDLE";
7631
+ /**
7632
+ * Some of the bookings it reaches run, at their date, beside a plan the
7633
+ * replacement cannot run beside: not allowed there, without a price there
7634
+ * in the booking's rhythm, or in a longer rhythm than the plan's. Carries
7635
+ * how many, and the replacement's add-on key and version.
7636
+ */
7637
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_CANNOT_RUN: "BUNDLE_RETIREMENT_REPLACEMENT_CANNOT_RUN";
7638
+ /** No running booking is on the version: there is nobody to tell. Carries add-on key and version. */
7639
+ readonly BUNDLE_RETIREMENT_NOTHING_AFFECTED: "BUNDLE_RETIREMENT_NOTHING_AFFECTED";
7640
+ /**
7641
+ * The booking is on an add-on version being retired, and was cancelled to
7642
+ * end before it would move, so it was never told and nothing moves it.
7643
+ * Reinstated, it would run on past the date on a version nobody sells;
7644
+ * booking the replacement once it has ended is the way. Carries the add-on
7645
+ * key, the version, the replacement's version and the day it can be booked
7646
+ * from.
7647
+ */
7648
+ readonly BUNDLE_RETIREMENT_REINSTATE_REFUSED: "BUNDLE_RETIREMENT_REINSTATE_REFUSED";
7649
+ /**
7650
+ * As `BUNDLE_RETIREMENT_REINSTATE_REFUSED`, where the replacement cannot
7651
+ * run beside the plan the subscription is on when the booking ends, or
7652
+ * beside one it is already set to move to after that, in any rhythm it
7653
+ * could be booked in, so there is no version of the add-on to book.
7654
+ * Carries the add-on key, the version and the replacement's version.
7655
+ */
7656
+ readonly BUNDLE_RETIREMENT_REINSTATE_REPLACEMENT_CANNOT_RUN: "BUNDLE_RETIREMENT_REINSTATE_REPLACEMENT_CANNOT_RUN";
7657
+ /**
7658
+ * As `BUNDLE_RETIREMENT_REINSTATE_REFUSED`, where the subscription ends by
7659
+ * the day the replacement could be booked from, so there is no day to
7660
+ * name. Carries the add-on key, the version and the replacement's version.
7661
+ */
7662
+ readonly BUNDLE_RETIREMENT_REINSTATE_SUBSCRIPTION_ENDS: "BUNDLE_RETIREMENT_REINSTATE_SUBSCRIPTION_ENDS";
7663
+ /**
7664
+ * The plan the add-on runs beside, or the rhythm it is billed in, changes
7665
+ * before the date the booking was told — by a change scheduled, or by a
7666
+ * retirement told that moves the subscription to another plan — so the
7667
+ * price a switch now would hold is not the one the booking pays until
7668
+ * then. Switching once the plan has changed, or waiting for the
7669
+ * date, is the way. Carries the add-on and the date.
7670
+ */
7671
+ readonly BUNDLE_RETIREMENT_SWITCH_PLAN_CHANGES: "BUNDLE_RETIREMENT_SWITCH_PLAN_CHANGES";
7672
+ /**
7673
+ * The add-on version the caller asked to switch a booking to is no longer
7674
+ * the one offered beside it — another is on sale, the booking moved, or
7675
+ * there is no offer. Nothing was switched. Carries the version named
7676
+ * (`bundleVersionId`) and the current `offer`, or `null`, so the page can
7677
+ * show it instead of guessing.
7678
+ */
7679
+ readonly BUNDLE_VERSION_OFFER_CHANGED: "BUNDLE_VERSION_OFFER_CHANGED";
6731
7680
  /** The subscription has ended; its plan can no longer be changed. */
6732
7681
  readonly SUBSCRIPTION_ENDED: "SUBSCRIPTION_ENDED";
6733
7682
  /** An active special contract blocks self-service plan changes. */
@@ -6762,6 +7711,16 @@ declare const BILLING_ERROR_CODES: {
6762
7711
  * day the booking can end.
6763
7712
  */
6764
7713
  readonly BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN: "BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN";
7714
+ /**
7715
+ * A bundle the tenant already holds can run on the plan they are moving
7716
+ * to, but the version it continues on from a retirement's date cannot.
7717
+ * Cancelling it lets the change through at once: the booking then ends
7718
+ * before that date and never reaches the version. Given while that date is
7719
+ * ahead and the booking is not cancelled yet; otherwise
7720
+ * `BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN` names the day it can end.
7721
+ * Carries the bundle, that version, its date and the plan.
7722
+ */
7723
+ readonly BUNDLE_REPLACEMENT_DOES_NOT_FIT_TARGET_PLAN: "BUNDLE_REPLACEMENT_DOES_NOT_FIT_TARGET_PLAN";
6765
7724
  /**
6766
7725
  * Features of the previewed bundle are already covered by the plan or by
6767
7726
  * another booked bundle. A warning rather than a blocker: paying twice is
@@ -6831,6 +7790,21 @@ declare const CONTRACT_ERROR_CODES: {
6831
7790
  * describes. Nothing was written; load the offer and conclude it again.
6832
7791
  */
6833
7792
  readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
7793
+ /**
7794
+ * An offer concludes a tenant's first contract, and this tenant has a
7795
+ * contract in force at the moment the offer's would take effect, or one
7796
+ * beginning after it. Concluded, the two would run side by side. Nothing
7797
+ * was written; a running subscription changes through its plan and its
7798
+ * add-ons. Carries the offer and the contract that runs.
7799
+ */
7800
+ readonly CHECKOUT_OFFER_CONTRACT_IN_FORCE: "CHECKOUT_OFFER_CONTRACT_IN_FORCE";
7801
+ /**
7802
+ * The offer names a version of an add-on the tenant has booked in another
7803
+ * version. Concluded, the contract would name a version the booking is not
7804
+ * on. Nothing was written; a booking changes its version through the offer
7805
+ * beside it. Carries the offer, the add-on, the booking and both versions.
7806
+ */
7807
+ readonly CHECKOUT_OFFER_ADD_ON_BOOKED_IN_ANOTHER_VERSION: "CHECKOUT_OFFER_ADD_ON_BOOKED_IN_ANOTHER_VERSION";
6834
7808
  readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
6835
7809
  readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
6836
7810
  readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
@@ -6842,6 +7816,11 @@ declare const CONTRACT_ERROR_CODES: {
6842
7816
  * would take effect. Nothing was written.
6843
7817
  */
6844
7818
  readonly SUBSCRIPTION_CONTRACT_CHANGED: "SUBSCRIPTION_CONTRACT_CHANGED";
7819
+ /**
7820
+ * A contract states a tax rate — `field` names where — other than the one
7821
+ * the installation's tax adapter decides for its subscriber.
7822
+ */
7823
+ readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED";
6845
7824
  };
6846
7825
  type ContractErrorCode = (typeof CONTRACT_ERROR_CODES)[keyof typeof CONTRACT_ERROR_CODES];
6847
7826
  /** The parties contracts are concluded with (`SubscriberService`), and their absence. */
@@ -6868,6 +7847,29 @@ declare const SUBSCRIBER_ERROR_CODES: {
6868
7847
  readonly SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "SUBSCRIBER_CORRECTION_CHANGES_NOTHING";
6869
7848
  /** The operator declared another legal entity: that is a transfer, not an edit. */
6870
7849
  readonly SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER";
7850
+ /**
7851
+ * A contact change named whether the subscriber is a business. That is part
7852
+ * of its tax origin and changes as a recorded change naming who made it.
7853
+ */
7854
+ readonly SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT: "SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT";
7855
+ /** A change of the subscriber's contact details or business status did not say who makes it. */
7856
+ readonly SUBSCRIBER_CHANGE_ACTOR_REQUIRED: "SUBSCRIBER_CHANGE_ACTOR_REQUIRED";
7857
+ /**
7858
+ * Where a tax adapter decides, a contract names its subscriber only once
7859
+ * the address an invoice names is complete (`SC-PRIC-032`): a party copied
7860
+ * onto a contract incomplete cannot be completed afterwards. Carries
7861
+ * `missing`, the empty fields, for a screen to name by their labels; the
7862
+ * shipped sentence names all four rather than the keys.
7863
+ */
7864
+ readonly SUBSCRIBER_IDENTITY_INCOMPLETE: "SUBSCRIBER_IDENTITY_INCOMPLETE";
7865
+ /**
7866
+ * A change of whether the subscriber is a business states no reason. It
7867
+ * decides the tax treatment of the next invoice, so the change log keeps
7868
+ * why it moved (`SC-PRIC-043`).
7869
+ */
7870
+ readonly SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED: "SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED";
7871
+ /** A check of the subscriber's VAT identification number was asked for, and it holds none. */
7872
+ readonly SUBSCRIBER_VAT_ID_MISSING: "SUBSCRIBER_VAT_ID_MISSING";
6871
7873
  };
6872
7874
  type SubscriberErrorCode = (typeof SUBSCRIBER_ERROR_CODES)[keyof typeof SUBSCRIBER_ERROR_CODES];
6873
7875
  /** Self-service registration funnel (`PendingRegistration`). */
@@ -6985,6 +7987,31 @@ declare const MAINTENANCE_ERROR_CODES: {
6985
7987
  readonly MAINTENANCE_MESSAGE_TOO_LONG: "MAINTENANCE_MESSAGE_TOO_LONG";
6986
7988
  };
6987
7989
  type MaintenanceErrorCode = (typeof MAINTENANCE_ERROR_CODES)[keyof typeof MAINTENANCE_ERROR_CODES];
7990
+ /** Codes of the installation's tax adapter (ADR 0013). */
7991
+ declare const TAX_ERROR_CODES: {
7992
+ /**
7993
+ * The tax adapter answers that it does not support the subscriber's case;
7994
+ * `adapter` names it and `reason` is its sentence. Nothing is concluded with
7995
+ * a guessed tax (`SC-PRIC-039`).
7996
+ */
7997
+ readonly TAX_TREATMENT_NOT_SUPPORTED: "TAX_TREATMENT_NOT_SUPPORTED";
7998
+ /**
7999
+ * The tax adapter needs the VAT identification number checked to treat the
8000
+ * case, and the check did not complete — the service is unavailable, timed
8001
+ * out, or answered in a way the adapter cannot read (`503`). Nothing is
8002
+ * decided in the subscriber's favour on a number not checked
8003
+ * (`SC-PRIC-040`): try again later. `adapter` names the adapter and
8004
+ * `reason` says why.
8005
+ */
8006
+ readonly TAX_VAT_ID_CHECK_NOT_COMPLETED: "TAX_VAT_ID_CHECK_NOT_COMPLETED";
8007
+ /**
8008
+ * A VAT identification number was to be checked, and `config/saas.yaml`
8009
+ * names no tax adapter, which is what names the service to check with
8010
+ * (`409`).
8011
+ */
8012
+ readonly TAX_VAT_ID_CHECK_NOT_AVAILABLE: "TAX_VAT_ID_CHECK_NOT_AVAILABLE";
8013
+ };
8014
+ type TaxErrorCode = (typeof TAX_ERROR_CODES)[keyof typeof TAX_ERROR_CODES];
6988
8015
  /**
6989
8016
  * Every exception code the platform emits, in one object.
6990
8017
  *
@@ -6993,6 +8020,27 @@ type MaintenanceErrorCode = (typeof MAINTENANCE_ERROR_CODES)[keyof typeof MAINTE
6993
8020
  * removing one may not.
6994
8021
  */
6995
8022
  declare const PLATFORM_ERROR_CODES: {
8023
+ /**
8024
+ * The tax adapter answers that it does not support the subscriber's case;
8025
+ * `adapter` names it and `reason` is its sentence. Nothing is concluded with
8026
+ * a guessed tax (`SC-PRIC-039`).
8027
+ */
8028
+ readonly TAX_TREATMENT_NOT_SUPPORTED: "TAX_TREATMENT_NOT_SUPPORTED";
8029
+ /**
8030
+ * The tax adapter needs the VAT identification number checked to treat the
8031
+ * case, and the check did not complete — the service is unavailable, timed
8032
+ * out, or answered in a way the adapter cannot read (`503`). Nothing is
8033
+ * decided in the subscriber's favour on a number not checked
8034
+ * (`SC-PRIC-040`): try again later. `adapter` names the adapter and
8035
+ * `reason` says why.
8036
+ */
8037
+ readonly TAX_VAT_ID_CHECK_NOT_COMPLETED: "TAX_VAT_ID_CHECK_NOT_COMPLETED";
8038
+ /**
8039
+ * A VAT identification number was to be checked, and `config/saas.yaml`
8040
+ * names no tax adapter, which is what names the service to check with
8041
+ * (`409`).
8042
+ */
8043
+ readonly TAX_VAT_ID_CHECK_NOT_AVAILABLE: "TAX_VAT_ID_CHECK_NOT_AVAILABLE";
6996
8044
  /** The application is locked for maintenance; the body carries the window. */
6997
8045
  readonly MAINTENANCE: "MAINTENANCE";
6998
8046
  /** A window is already open: move or cancel it before announcing another. */
@@ -7069,6 +8117,29 @@ declare const PLATFORM_ERROR_CODES: {
7069
8117
  readonly SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "SUBSCRIBER_CORRECTION_CHANGES_NOTHING";
7070
8118
  /** The operator declared another legal entity: that is a transfer, not an edit. */
7071
8119
  readonly SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER";
8120
+ /**
8121
+ * A contact change named whether the subscriber is a business. That is part
8122
+ * of its tax origin and changes as a recorded change naming who made it.
8123
+ */
8124
+ readonly SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT: "SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT";
8125
+ /** A change of the subscriber's contact details or business status did not say who makes it. */
8126
+ readonly SUBSCRIBER_CHANGE_ACTOR_REQUIRED: "SUBSCRIBER_CHANGE_ACTOR_REQUIRED";
8127
+ /**
8128
+ * Where a tax adapter decides, a contract names its subscriber only once
8129
+ * the address an invoice names is complete (`SC-PRIC-032`): a party copied
8130
+ * onto a contract incomplete cannot be completed afterwards. Carries
8131
+ * `missing`, the empty fields, for a screen to name by their labels; the
8132
+ * shipped sentence names all four rather than the keys.
8133
+ */
8134
+ readonly SUBSCRIBER_IDENTITY_INCOMPLETE: "SUBSCRIBER_IDENTITY_INCOMPLETE";
8135
+ /**
8136
+ * A change of whether the subscriber is a business states no reason. It
8137
+ * decides the tax treatment of the next invoice, so the change log keeps
8138
+ * why it moved (`SC-PRIC-043`).
8139
+ */
8140
+ readonly SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED: "SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED";
8141
+ /** A check of the subscriber's VAT identification number was asked for, and it holds none. */
8142
+ readonly SUBSCRIBER_VAT_ID_MISSING: "SUBSCRIBER_VAT_ID_MISSING";
7072
8143
  readonly CHECKOUT_OFFER_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_LINE_ITEMS_REQUIRED";
7073
8144
  readonly CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED: "CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED";
7074
8145
  readonly CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED";
@@ -7103,6 +8174,21 @@ declare const PLATFORM_ERROR_CODES: {
7103
8174
  * describes. Nothing was written; load the offer and conclude it again.
7104
8175
  */
7105
8176
  readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
8177
+ /**
8178
+ * An offer concludes a tenant's first contract, and this tenant has a
8179
+ * contract in force at the moment the offer's would take effect, or one
8180
+ * beginning after it. Concluded, the two would run side by side. Nothing
8181
+ * was written; a running subscription changes through its plan and its
8182
+ * add-ons. Carries the offer and the contract that runs.
8183
+ */
8184
+ readonly CHECKOUT_OFFER_CONTRACT_IN_FORCE: "CHECKOUT_OFFER_CONTRACT_IN_FORCE";
8185
+ /**
8186
+ * The offer names a version of an add-on the tenant has booked in another
8187
+ * version. Concluded, the contract would name a version the booking is not
8188
+ * on. Nothing was written; a booking changes its version through the offer
8189
+ * beside it. Carries the offer, the add-on, the booking and both versions.
8190
+ */
8191
+ readonly CHECKOUT_OFFER_ADD_ON_BOOKED_IN_ANOTHER_VERSION: "CHECKOUT_OFFER_ADD_ON_BOOKED_IN_ANOTHER_VERSION";
7106
8192
  readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
7107
8193
  readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
7108
8194
  readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
@@ -7114,6 +8200,11 @@ declare const PLATFORM_ERROR_CODES: {
7114
8200
  * would take effect. Nothing was written.
7115
8201
  */
7116
8202
  readonly SUBSCRIPTION_CONTRACT_CHANGED: "SUBSCRIPTION_CONTRACT_CHANGED";
8203
+ /**
8204
+ * A contract states a tax rate — `field` names where — other than the one
8205
+ * the installation's tax adapter decides for its subscriber.
8206
+ */
8207
+ readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED";
7117
8208
  /**
7118
8209
  * Feature not covered by the plan. Defined in `upsell.types.ts` because the
7119
8210
  * upsell body type is built around it; re-exported here so an exhaustive
@@ -7273,6 +8364,16 @@ declare const PLATFORM_ERROR_CODES: {
7273
8364
  * to pick, so the way past it is the add-on ending.
7274
8365
  */
7275
8366
  readonly RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW: "RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW";
8367
+ /**
8368
+ * As `RETIREMENT_SWITCH_BUNDLE_CANNOT_FOLLOW`, where only the version the
8369
+ * add-on continues on from a retirement's date cannot run beside the
8370
+ * replacement's plan. The version it is on can, so cancelling it — it then
8371
+ * ends before that date — lets the switch through. Given while that date
8372
+ * is ahead and the add-on is not cancelled yet; otherwise the earlier code
8373
+ * names the day it can end. Carries the add-on, that version, its date and
8374
+ * the plan.
8375
+ */
8376
+ readonly RETIREMENT_SWITCH_BUNDLE_REPLACEMENT_CANNOT_FOLLOW: "RETIREMENT_SWITCH_BUNDLE_REPLACEMENT_CANNOT_FOLLOW";
7276
8377
  /**
7277
8378
  * The subscription takes no switch now: a change is scheduled, it has
7278
8379
  * ended, or its plan is held for a special contract.
@@ -7283,6 +8384,69 @@ declare const PLATFORM_ERROR_CODES: {
7283
8384
  * the retirement as it now stands.
7284
8385
  */
7285
8386
  readonly RETIREMENT_SWITCH_CHANGED: "RETIREMENT_SWITCH_CHANGED";
8387
+ /**
8388
+ * The add-on version is still on sale: a booking made after the
8389
+ * announcement would be on it without having been told. Carries the
8390
+ * add-on key and the version.
8391
+ */
8392
+ readonly BUNDLE_RETIREMENT_VERSION_ON_SALE: "BUNDLE_RETIREMENT_VERSION_ON_SALE";
8393
+ /** The replacement is not on sale, so no booking can continue on it. Carries add-on key and version. */
8394
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_NOT_ON_SALE: "BUNDLE_RETIREMENT_REPLACEMENT_NOT_ON_SALE";
8395
+ /**
8396
+ * The replacement is a version of another add-on. A booking continues on
8397
+ * a version of its own add-on, so it stays the same booking with its term.
8398
+ * Carries both add-on keys.
8399
+ */
8400
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_OF_ANOTHER_BUNDLE: "BUNDLE_RETIREMENT_REPLACEMENT_OF_ANOTHER_BUNDLE";
8401
+ /**
8402
+ * Some of the bookings it reaches run, at their date, beside a plan the
8403
+ * replacement cannot run beside: not allowed there, without a price there
8404
+ * in the booking's rhythm, or in a longer rhythm than the plan's. Carries
8405
+ * how many, and the replacement's add-on key and version.
8406
+ */
8407
+ readonly BUNDLE_RETIREMENT_REPLACEMENT_CANNOT_RUN: "BUNDLE_RETIREMENT_REPLACEMENT_CANNOT_RUN";
8408
+ /** No running booking is on the version: there is nobody to tell. Carries add-on key and version. */
8409
+ readonly BUNDLE_RETIREMENT_NOTHING_AFFECTED: "BUNDLE_RETIREMENT_NOTHING_AFFECTED";
8410
+ /**
8411
+ * The booking is on an add-on version being retired, and was cancelled to
8412
+ * end before it would move, so it was never told and nothing moves it.
8413
+ * Reinstated, it would run on past the date on a version nobody sells;
8414
+ * booking the replacement once it has ended is the way. Carries the add-on
8415
+ * key, the version, the replacement's version and the day it can be booked
8416
+ * from.
8417
+ */
8418
+ readonly BUNDLE_RETIREMENT_REINSTATE_REFUSED: "BUNDLE_RETIREMENT_REINSTATE_REFUSED";
8419
+ /**
8420
+ * As `BUNDLE_RETIREMENT_REINSTATE_REFUSED`, where the replacement cannot
8421
+ * run beside the plan the subscription is on when the booking ends, or
8422
+ * beside one it is already set to move to after that, in any rhythm it
8423
+ * could be booked in, so there is no version of the add-on to book.
8424
+ * Carries the add-on key, the version and the replacement's version.
8425
+ */
8426
+ readonly BUNDLE_RETIREMENT_REINSTATE_REPLACEMENT_CANNOT_RUN: "BUNDLE_RETIREMENT_REINSTATE_REPLACEMENT_CANNOT_RUN";
8427
+ /**
8428
+ * As `BUNDLE_RETIREMENT_REINSTATE_REFUSED`, where the subscription ends by
8429
+ * the day the replacement could be booked from, so there is no day to
8430
+ * name. Carries the add-on key, the version and the replacement's version.
8431
+ */
8432
+ readonly BUNDLE_RETIREMENT_REINSTATE_SUBSCRIPTION_ENDS: "BUNDLE_RETIREMENT_REINSTATE_SUBSCRIPTION_ENDS";
8433
+ /**
8434
+ * The plan the add-on runs beside, or the rhythm it is billed in, changes
8435
+ * before the date the booking was told — by a change scheduled, or by a
8436
+ * retirement told that moves the subscription to another plan — so the
8437
+ * price a switch now would hold is not the one the booking pays until
8438
+ * then. Switching once the plan has changed, or waiting for the
8439
+ * date, is the way. Carries the add-on and the date.
8440
+ */
8441
+ readonly BUNDLE_RETIREMENT_SWITCH_PLAN_CHANGES: "BUNDLE_RETIREMENT_SWITCH_PLAN_CHANGES";
8442
+ /**
8443
+ * The add-on version the caller asked to switch a booking to is no longer
8444
+ * the one offered beside it — another is on sale, the booking moved, or
8445
+ * there is no offer. Nothing was switched. Carries the version named
8446
+ * (`bundleVersionId`) and the current `offer`, or `null`, so the page can
8447
+ * show it instead of guessing.
8448
+ */
8449
+ readonly BUNDLE_VERSION_OFFER_CHANGED: "BUNDLE_VERSION_OFFER_CHANGED";
7286
8450
  /** The subscription has ended; its plan can no longer be changed. */
7287
8451
  readonly SUBSCRIPTION_ENDED: "SUBSCRIPTION_ENDED";
7288
8452
  /** An active special contract blocks self-service plan changes. */
@@ -7317,6 +8481,16 @@ declare const PLATFORM_ERROR_CODES: {
7317
8481
  * day the booking can end.
7318
8482
  */
7319
8483
  readonly BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN: "BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN";
8484
+ /**
8485
+ * A bundle the tenant already holds can run on the plan they are moving
8486
+ * to, but the version it continues on from a retirement's date cannot.
8487
+ * Cancelling it lets the change through at once: the booking then ends
8488
+ * before that date and never reaches the version. Given while that date is
8489
+ * ahead and the booking is not cancelled yet; otherwise
8490
+ * `BUNDLE_BOOKING_DOES_NOT_FIT_TARGET_PLAN` names the day it can end.
8491
+ * Carries the bundle, that version, its date and the plan.
8492
+ */
8493
+ readonly BUNDLE_REPLACEMENT_DOES_NOT_FIT_TARGET_PLAN: "BUNDLE_REPLACEMENT_DOES_NOT_FIT_TARGET_PLAN";
7320
8494
  /**
7321
8495
  * Features of the previewed bundle are already covered by the plan or by
7322
8496
  * another booked bundle. A warning rather than a blocker: paying twice is
@@ -7421,6 +8595,13 @@ declare const PLATFORM_ERROR_CODES: {
7421
8595
  readonly PLAN_NOT_FOUND: "PLAN_NOT_FOUND";
7422
8596
  readonly PLAN_VERSION_NOT_FOUND: "PLAN_VERSION_NOT_FOUND";
7423
8597
  readonly BUNDLE_NOT_FOUND: "BUNDLE_NOT_FOUND";
8598
+ /**
8599
+ * Bookings told that their add-on version is being retired have still to
8600
+ * move onto a version of this add-on — waiting for their notice, for their
8601
+ * date, or past it — and a deleted add-on is booked by nothing, the move
8602
+ * included. Carries how many, and the add-on's key.
8603
+ */
8604
+ readonly BUNDLE_DELETE_WHILE_RETIREMENT_MOVES_PENDING: "BUNDLE_DELETE_WHILE_RETIREMENT_MOVES_PENDING";
7424
8605
  readonly BUNDLE_VERSION_NOT_FOUND: "BUNDLE_VERSION_NOT_FOUND";
7425
8606
  readonly FEATURE_NOT_FOUND: "FEATURE_NOT_FOUND";
7426
8607
  readonly QUOTA_NOT_FOUND: "QUOTA_NOT_FOUND";
@@ -7493,7 +8674,7 @@ declare const PLATFORM_ERROR_CODES: {
7493
8674
  /** Email already taken (mapped from `PlatformUserExistsError`). */
7494
8675
  readonly EMAIL_EXISTS: "EMAIL_EXISTS";
7495
8676
  };
7496
- type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | SubscriberErrorCode | RegistrationErrorCode | PaymentErrorCode | SettingsErrorCode | MaintenanceErrorCode;
8677
+ type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | SubscriberErrorCode | RegistrationErrorCode | PaymentErrorCode | SettingsErrorCode | MaintenanceErrorCode | TaxErrorCode;
7497
8678
  /**
7498
8679
  * Shape of a coded error response.
7499
8680
  *
@@ -7577,6 +8758,7 @@ declare const OPTIONAL_CANONICAL_MODELS: {
7577
8758
  readonly MaintenanceWindow: readonly ["core.maintenanceWindows"];
7578
8759
  readonly SubscriptionNotice: readonly ["tenantBilling.subscriptionNotices"];
7579
8760
  readonly VersionRetirement: readonly ["tenantBilling.versionRetirements"];
8761
+ readonly BundleVersionRetirement: readonly ["tenantBilling.bundleVersionRetirements"];
7580
8762
  readonly SubscriberLedgerEntry: readonly ["entitlement.subscriberLedgerRepository"];
7581
8763
  readonly PromoCodeHold: readonly ["promo.holdRepository"];
7582
8764
  };
@@ -7881,6 +9063,14 @@ interface PendingRegistration {
7881
9063
  country: string | null;
7882
9064
  vatId: string | null;
7883
9065
  taxNumber: string | null;
9066
+ /** Whether the sign-up is a business, as step 4 says; `null` where it did not say. */
9067
+ business: boolean | null;
9068
+ /**
9069
+ * The check of `vatId` step 4 made, outside any transaction, where the tax
9070
+ * adapter needed a validated number to treat the sign-up; `null` where it
9071
+ * needed none. The subscriber takes it over when it is created.
9072
+ */
9073
+ vatIdCheck: VatIdCheck | null;
7884
9074
  /** The gateway's session for the payment method, unique within `checkoutGatewayAccount`. */
7885
9075
  checkoutSessionId: string | null;
7886
9076
  /** The account in `config/saas.yaml#payments.accounts` the session was opened at. */
@@ -7925,6 +9115,8 @@ interface PendingRegistrationUpdateInput {
7925
9115
  country?: string | null;
7926
9116
  vatId?: string | null;
7927
9117
  taxNumber?: string | null;
9118
+ business?: boolean | null;
9119
+ vatIdCheck?: VatIdCheck | null;
7928
9120
  checkoutSessionId?: string | null;
7929
9121
  checkoutGatewayAccount?: string | null;
7930
9122
  gatewayCustomerRef?: string | null;
@@ -8179,7 +9371,12 @@ interface ConfiguratorPlanMarketing {
8179
9371
  */
8180
9372
  interface ConfiguratorMarketingProvider {
8181
9373
  listPlanMarketing(): ConfiguratorPlanMarketing[];
8182
- getVatRate(): number;
9374
+ /**
9375
+ * The rate the configurator shows. Required where config/saas.yaml names no
9376
+ * tax adapter; left out where it names one, whose rate for a subscriber in
9377
+ * the issuer's country is shown instead.
9378
+ */
9379
+ getVatRate?(): number;
8183
9380
  getCurrency(): string;
8184
9381
  }
8185
9382
  /**
@@ -8360,6 +9557,13 @@ interface RegistrationBillingDetails {
8360
9557
  country: string;
8361
9558
  vatId?: string | null;
8362
9559
  taxNumber?: string | null;
9560
+ /**
9561
+ * Whether the sign-up is a business. A tax adapter decides from it — a
9562
+ * business elsewhere in the European Union, for instance, is charged under
9563
+ * the reverse charge — and refuses the step where it needs it and it is
9564
+ * missing.
9565
+ */
9566
+ business?: boolean | null;
8363
9567
  }
8364
9568
  interface StartCheckoutInput {
8365
9569
  pendingRegistrationId: string;
@@ -8616,10 +9820,21 @@ interface CanonicalSubscriberRow {
8616
9820
  vatId: string | null;
8617
9821
  taxNumber: string | null;
8618
9822
  invoiceEmail: string | null;
9823
+ business: boolean | null;
8619
9824
  migrated: boolean;
8620
9825
  createdAt: Date;
8621
9826
  updatedAt: Date;
8622
9827
  }
9828
+ /** A `subscriber_tax_origin_changes` row as either adapter reads it back. */
9829
+ interface CanonicalSubscriberTaxOriginChangeRow {
9830
+ id: string;
9831
+ subscriberId: string;
9832
+ previous: unknown;
9833
+ changed: unknown;
9834
+ changedBy: string;
9835
+ changedAt: Date;
9836
+ reason: string | null;
9837
+ }
8623
9838
  /** A `subscriber_corrections` row as either adapter reads it back. */
8624
9839
  interface CanonicalSubscriberCorrectionRow {
8625
9840
  id: string;
@@ -8639,6 +9854,7 @@ declare function formatCustomerNumber(prefix: string, sequence: number): string;
8639
9854
  /** `tenantId` is the tenant the subscriber's live link names, read beside the row. */
8640
9855
  declare function toSubscriberRecord(row: CanonicalSubscriberRow, tenantId: string | null): SubscriberRecord;
8641
9856
  declare function toSubscriberCorrectionRecord(row: CanonicalSubscriberCorrectionRow): SubscriberCorrectionRecord;
9857
+ declare function toSubscriberTaxOriginChangeRecord(row: CanonicalSubscriberTaxOriginChangeRow): SubscriberTaxOriginChangeRecord;
8642
9858
  /**
8643
9859
  * The part of a correction that changes something: every corrected field whose
8644
9860
  * stored value differs, with the value it replaces. Both adapters decide this
@@ -8656,7 +9872,7 @@ declare function contractPartiesOf(subscriber: SubscriberRecord, issuer: PlanCat
8656
9872
  * verified with as its invoice email, and the billing address and tax
8657
9873
  * identifiers step 4 took.
8658
9874
  */
8659
- declare function subscriberFromRegistration(pending: Pick<PendingRegistration, 'tenantName' | 'email' | 'addressLine1' | 'addressLine2' | 'postalCode' | 'city' | 'country' | 'vatId' | 'taxNumber'>): NewSubscriberDetails;
9875
+ declare function subscriberFromRegistration(pending: Pick<PendingRegistration, 'tenantName' | 'email' | 'addressLine1' | 'addressLine2' | 'postalCode' | 'city' | 'country' | 'vatId' | 'taxNumber' | 'business' | 'vatIdCheck'>): NewSubscriberDetails;
8660
9876
 
8661
9877
  /** The payment method types, in the order a form offers them. */
8662
9878
  declare const PAYMENT_METHOD_TYPES: readonly PaymentMethodType[];
@@ -8733,9 +9949,10 @@ declare function refuseForeignPaymentMethodReference(recorded: Pick<CanonicalSub
8733
9949
  /**
8734
9950
  * A `subscription_bundles` row as either adapter reads it back.
8735
9951
  *
8736
- * The three billing columns are optional because a Prisma client generated from
8737
- * a schema that predates them returns a row without them; an absent column
8738
- * reads as null, the same as a booking made before they existed.
9952
+ * The three billing columns and the two of a scheduled switch are optional
9953
+ * because a Prisma client generated from a schema that predates them returns a
9954
+ * row without them; an absent column reads as null, the same as a booking made
9955
+ * before they existed.
8739
9956
  */
8740
9957
  interface CanonicalSubscriptionBundleRow {
8741
9958
  id: string;
@@ -8746,6 +9963,8 @@ interface CanonicalSubscriptionBundleRow {
8746
9963
  billingCycle?: string | null;
8747
9964
  currentPeriodStart?: Date | null;
8748
9965
  currentPeriodEnd?: Date | null;
9966
+ pendingBundleVersionId?: string | null;
9967
+ pendingVersionEffectiveAt?: Date | null;
8749
9968
  canceledAt: Date | null;
8750
9969
  canceledEffectiveAt: Date | null;
8751
9970
  createdAt: Date;
@@ -8769,6 +9988,8 @@ interface CanonicalContractRow {
8769
9988
  subscriberSnapshot: unknown;
8770
9989
  issuerSnapshot: unknown;
8771
9990
  partiesMigrated: boolean;
9991
+ /** JSON; see `toTaxTreatment`. */
9992
+ taxTreatment: unknown;
8772
9993
  status: string;
8773
9994
  effectiveFrom: Date;
8774
9995
  effectiveUntil: Date | null;
@@ -8823,6 +10044,100 @@ interface CanonicalRunningContractRow {
8823
10044
  /** One running contract, and the legal name on its issuer copy where it has one. */
8824
10045
  declare function toRunningContractIssuer(row: CanonicalRunningContractRow): RunningContractIssuer;
8825
10046
 
10047
+ /**
10048
+ * A VAT identification number in the one form it is stored, compared and
10049
+ * checked in: upper case, without the spaces, dots and hyphens it is often
10050
+ * written with. `atu 123.456-78` is `ATU12345678` — the same number, so
10051
+ * entering it in another spelling moves nothing. `null` where nothing is left.
10052
+ * The platform settles every number it is given with this, and a form that
10053
+ * asks whether a number changed compares with it too.
10054
+ */
10055
+ declare function canonicalVatId(written: string): string | null;
10056
+ /** A `subscriber_vat_id_checks` row as either adapter reads it back. */
10057
+ interface CanonicalSubscriberVatIdCheckRow {
10058
+ id: string;
10059
+ subscriberId: string;
10060
+ vatId: string;
10061
+ checkedAt: Date;
10062
+ valid: boolean;
10063
+ service: string;
10064
+ confirmation: unknown;
10065
+ recordedAt: Date;
10066
+ }
10067
+ /**
10068
+ * What an adapter decides a subscriber's treatment from: the record as it
10069
+ * stands, and the check that counts for its number now. The number counts as
10070
+ * validated only when that check is of the number the subscriber has and found
10071
+ * it valid.
10072
+ */
10073
+ declare function taxOriginOf(subscriber: Pick<SubscriberRecord, SubscriberTaxOriginField>, currentCheck: VatIdCheck | null): SubscriberTaxOrigin;
10074
+ /** The subscriber's number, and since when it holds it. */
10075
+ interface HeldVatId {
10076
+ vatId: string | null;
10077
+ /**
10078
+ * When the number was last set by a correction; `null` while it is the one
10079
+ * the subscriber was created with.
10080
+ */
10081
+ vatIdSince: Date | null;
10082
+ }
10083
+ /**
10084
+ * Whether a check just recorded is the one that counts from now on, given the
10085
+ * subscriber's number and the check that counts now. Only a check of the
10086
+ * number the subscriber holds, completed while it held it, and never over a
10087
+ * check that completed later:
10088
+ *
10089
+ * - A check completed before the number was last set says nothing about it:
10090
+ * the number was away in between, and may have been revoked meanwhile.
10091
+ * - Two checks of one number can run side by side, and the one written last
10092
+ * is not the latest — an older "valid" written after a newer "invalid" would
10093
+ * validate a number the latest check refused. Of two checks with the same
10094
+ * date, the one written last counts.
10095
+ *
10096
+ * `vatIdSince` and `checkedAt` are both the platform's clock; between two
10097
+ * instances, the window this leaves is the difference between their clocks.
10098
+ */
10099
+ declare function keepsVatIdCheck(held: HeldVatId, counting: VatIdCheck | null, check: VatIdCheck): boolean;
10100
+ /** A recorded check read back; a confirmation of another shape reads as empty. */
10101
+ declare function toSubscriberVatIdCheckRecord(row: CanonicalSubscriberVatIdCheckRow): SubscriberVatIdCheckRecord;
10102
+ /** A treatment as it is stored on a contract. */
10103
+ declare function taxTreatmentToJson(treatment: TaxTreatment): Record<string, unknown>;
10104
+ /** A stored treatment read back, or `null` where none is stored or it has another shape. */
10105
+ declare function toTaxTreatment(value: unknown): TaxTreatment | null;
10106
+ /** What a write moves of a subscriber's tax origin, and what follows from it. */
10107
+ interface TaxOriginWrite {
10108
+ /** The values the write replaces, holding only the fields it moves. */
10109
+ previous: SubscriberTaxOriginValues;
10110
+ /** The values it writes, holding only the fields it moves. */
10111
+ changed: SubscriberTaxOriginValues;
10112
+ /** Whether it moves anything, and so has a change to record. */
10113
+ moved: boolean;
10114
+ /**
10115
+ * Whether it moves the VAT identification number. The check that counted
10116
+ * for the old number then counts no more — it says nothing about the new
10117
+ * one, nor about the old one should it come back later — while the check
10118
+ * itself stays recorded; and the number held is held since this write
10119
+ * (`HeldVatId.vatIdSince`).
10120
+ */
10121
+ endsCountingVatIdCheck: boolean;
10122
+ }
10123
+ /**
10124
+ * What a write moves of the tax origin: every field named whose stored value
10125
+ * differs, with the value it replaces. Every adapter asks this under the lock
10126
+ * it read `current` with, and applies the answer: a change is recorded only
10127
+ * when it moved something.
10128
+ */
10129
+ declare function taxOriginWrite(current: Pick<SubscriberRecord, SubscriberTaxOriginField>, next: SubscriberTaxOriginValues): TaxOriginWrite;
10130
+ /** Stored tax origin values read back, holding only the fields that are there. */
10131
+ declare function toTaxOriginValues(value: unknown): SubscriberTaxOriginValues;
10132
+ /**
10133
+ * A check of a VAT identification number as a store gives it back. A sign-up
10134
+ * keeps its check where the application's repository puts it — often a JSON
10135
+ * column, which hands `checkedAt` back as text — so it is read again here,
10136
+ * once. Anything that is not a whole check reads as none: a number never
10137
+ * counts as validated on a record that cannot say so.
10138
+ */
10139
+ declare function vatIdCheckFromStore(value: unknown): VatIdCheck | null;
10140
+
8826
10141
  /** Why a version is editable (for UI badges + audit logs). */
8827
10142
  type VersionEditableReason = 'draft' | 'pre-active';
8828
10143
  interface VersionEditability {
@@ -8904,4 +10219,4 @@ declare function resolveErrorMessage(body: ResolvableErrorBody, overrides?: Part
8904
10219
 
8905
10220
  declare const ERROR_MESSAGES_DE: Record<PlatformErrorCode, string>;
8906
10221
 
8907
- 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 AuditActor, 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, CUSTOM_LIMITS_KEYS, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalMaintenanceWindowRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalRunningContractRow, type CanonicalSubscriberChargeRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberRow, type CanonicalSubscriptionBundleRow, type CanonicalSubscriptionNoticeRow, type CanonicalVersionRetirementRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type CatalogVersionKind, 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 ConcurrencyGate, 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 CustomLimits, 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, MAINTENANCE_CAPABILITY, MAINTENANCE_ERROR_CODES, MAINTENANCE_MESSAGE_MAX_LENGTH, MAINTENANCE_STATE_MAX_AGE_SECONDS, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type MaintenanceErrorCode, type MaintenanceLockView, type MaintenanceNotificationPort, type MaintenanceOverview, type MaintenanceStatusView, type MaintenanceUnlockView, type MaintenanceWindowChanges, type MaintenanceWindowEvent, type MaintenanceWindowPort, type MaintenanceWindowRecord, type MaintenanceWindowStage, type MaintenanceWindowStatus, type MaintenanceWindowView, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, NO_SCHEDULED_CHANGE, type NewContractLineItemData, type NewMaintenanceWindow, type NewSettingsChange, type NewSubscriberCharge, type NewSubscriberDetails, type NewSubscriptionContractData, type NewVersionRetirement, type NoticeToRecord, OPTIONAL_CANONICAL_MODELS, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, type OptionalBundleMember, type OptionalCanonicalModel, type OrderlyRetirementSettings, 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, PersistenceRefusal, type PersistenceRefusalReason, 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 PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformJobActor, 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, RETIREMENT_REMINDER_LEAD_DAYS, type ReadCustomLimits, 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 RetiredVersionRef, type RetirementAnnounced, type RetirementBlocker, type RetirementMoveRun, type RetirementPreview, type RetirementProgress, type RetirementReachedRow, type RetirementSide, type RetirementSkipReason, type RetirementSkippedRow, type RetirementSwitchResult, type RetirementSwitchTerms, 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 ScheduledChangeColumns, type ScheduledPlanChangeInput, type SecretSealer, 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 SubscriptionNotice, type SubscriptionNoticeDelivery, type SubscriptionNoticeKey, type SubscriptionNoticeKind, type SubscriptionNoticePort, type SubscriptionNoticeRecord, type SubscriptionNoticeRepository, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SupersedeSubscriptionContractData, type SyncDiscoveryResult, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionUsage, 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, VERSION_RETIREMENT_CAPABILITY, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionOffer, type VersionOfferClass, type VersionOfferFields, type VersionOfferSide, type VersionOfferView, type VersionOfferedNotice, type VersionRetiredNotice, type VersionRetirementRecord, type VersionRetirementReminder, type VersionRetirementRepository, type VersionRetirementView, type VersionSale, type VersionSaleDates, type VersionSaleKind, type VersionSwitchResult, type VersionWindow, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleKeyTaken, bundleStemDefaults, canonicalJson, catalogDraftExists, catalogVersionAlreadyPublished, catalogVersionGone, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, classifyVersionOffer, collectUnsatisfiedRequires, computeIncludedVat, concurrencyGate, concurrencyGateOf, contractPartiesOf, coverageExcludingSelf, customLimitsReader, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, grossFromNet, identityCorrectionDelta, isBundleRedundant, isForeignPaymentMethodReferenceError, isMaintenanceAnnouncementLapsed, isMaintenanceOverrun, isPaymentCallbackRejectedError, isPersistenceRefusal, isPlatformUserExistsError, isVersionActiveAt, isVersionEditable, issuerIdentityOf, keepOneRecommended, maintenanceRetryAfterSeconds, maintenanceStatusOf, maintenanceWindowStatusOf, maintenanceWindowViewOf, marketingProjectionTaken, membersLeftOut, missingRequiresFor, movedIdentityFields, netFromGross, noActivePlanVersion, parseZonedInstant, percentOf, pickActivePromo, planCatalogSettingsOf, planKeyTaken, planNotInCatalog, previousUtcDay, promoCodeTaken, promoStatus, promotionOnPrice, prorate, readCustomLimits, readQuotaRecord, readQuotaValue, recordedIssuerIdentity, refuseForeignPaymentMethodReference, resolveBundleAvailability, resolveErrorMessage, retirementCostsTheSubscription, retirementReminderDueAt, retirementReminderIsDue, retirementSwitchTerms, roundToCents, sameLegalIdentity, scheduledChangeAfterWrite, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberChargeColumns, subscriberFromRegistration, subscriberPaymentMethodColumns, subscriptionBundleAlreadyCancelled, subscriptionBundleGone, subscriptionContractGone, subscriptionGone, sumToCents, toBundleStemRow, toCents, toContractLineItemRecord, toDecimalString, toMaintenanceWindowRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberChargeRecord, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriptionBundleRecord, toSubscriptionContractRecord, toSubscriptionNoticeRecord, toVersionRetirementRecord, versionOnSale, versionOnSaleOrNext, versionSale };
10222
+ 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 AdminSubscriberAttention, type AdminSubscriberCorrected, type AdminSubscriberHistoryEntry, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminTenantSubscriber, type AdminUserListFilter, type AdminUserListRow, type AdminVatIdCheckOutcome, type AppliedSettingsPort, type AppliedSettingsRecord, type AppliedSettingsValues, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditActor, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BUNDLE_PRICE_LOOKUP_LIMIT, BUNDLE_VERSION_RETIREMENT_CAPABILITY, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRetirementAnnounced, type BundleRetirementPreview, type BundleRetirementReachedRow, type BundleRetirementSkipReason, type BundleRetirementSkippedRow, type BundleRetirementSwitchResult, type BundleRetirementSwitchTerms, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionOfferView, type BundleVersionOfferedNotice, type BundleVersionRetiredNotice, type BundleVersionRetirementRecord, type BundleVersionRetirementReminder, type BundleVersionRetirementRepository, type BundleVersionRetirementView, type BundleVersionRow, type BundleVersionSide, type BundleVersionSwitchResult, CATALOGUE_KEYS, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, CUSTOM_LIMITS_KEYS, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalBundleVersionRetirementRow, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalMaintenanceWindowRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalRunningContractRow, type CanonicalSubscriberChargeRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberRow, type CanonicalSubscriberTaxOriginChangeRow, type CanonicalSubscriberVatIdCheckRow, type CanonicalSubscriptionBundleRow, type CanonicalSubscriptionNoticeRow, type CanonicalVersionRetirementRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type CatalogVersionKind, 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 ConcurrencyGate, 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 CustomLimits, 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 HeldVatId, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type IssuerCorrectionFault, type IssuerIdentityChange, type KpiCardDef, type KpiDisplayHint, LEGAL_IDENTITY_FIELDS, type LegalIdentity, type LegalIdentityField, MAINTENANCE_CAPABILITY, MAINTENANCE_ERROR_CODES, MAINTENANCE_MESSAGE_MAX_LENGTH, MAINTENANCE_STATE_MAX_AGE_SECONDS, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type MaintenanceErrorCode, type MaintenanceLockView, type MaintenanceNotificationPort, type MaintenanceOverview, type MaintenanceStatusView, type MaintenanceUnlockView, type MaintenanceWindowChanges, type MaintenanceWindowEvent, type MaintenanceWindowPort, type MaintenanceWindowRecord, type MaintenanceWindowStage, type MaintenanceWindowStatus, type MaintenanceWindowView, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, NO_SCHEDULED_CHANGE, type NewBundleVersionRetirement, type NewContractLineItemData, type NewMaintenanceWindow, type NewSettingsChange, type NewSubscriberCharge, type NewSubscriberDetails, type NewSubscriptionContractData, type NewVersionRetirement, type NotToldReasons, type NoticeToRecord, OPTIONAL_CANONICAL_MODELS, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, type OptionalBundleMember, type OptionalCanonicalModel, type OrderlyRetirementSettings, 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, PersistenceRefusal, type PersistenceRefusalReason, 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 PlanCatalogTax, type PlanCatalogTenantBilling, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformJobActor, 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, RETIREMENT_REMINDER_LEAD_DAYS, type ReadCustomLimits, type ReassignTenantAdminCliResult, type RecommendablePlan, type RecordSubscriberPaymentMethodData, type RecordSubscriberPaymentMethodOutcome, type RecordSubscriberPaymentMethodResult, type RecordedVatIdCheck, 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 RetiredBundleVersionRef, type RetiredVersionRef, type RetirementAnnounced, type RetirementBlocker, type RetirementMoveRun, type RetirementPreview, type RetirementPricedSide, type RetirementProgress, type RetirementReachedRow, type RetirementSide, type RetirementSkipReason, type RetirementSkippedRow, type RetirementSwitchResult, type RetirementSwitchTerms, type ReviewCatalogEntryData, type RlsBypassPort, type RunningContractIssuer, type RunningContractIssuers, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ACCOUNT_CAPABILITY, SUBSCRIBER_ATTENTION_CAPABILITY, SUBSCRIBER_ATTENTION_PAGE_SIZE, SUBSCRIBER_CORRECTION_CAPABILITY, SUBSCRIBER_ERROR_CODES, SUBSCRIBER_INVOICE_ADDRESS_FIELDS, SUBSCRIBER_STANDING_CAPABILITY, SUBSCRIBER_TAX_ORIGIN_FIELDS, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePayments, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledChangeColumns, type ScheduledPlanChangeInput, type SecretSealer, 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 SubscriberBusinessStatusData, type SubscriberBusinessStatusResult, 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 SubscriberInvoiceAddressField, type SubscriberLedgerRepository, type SubscriberPaymentMethodRecord, type SubscriberPaymentMethodReference, type SubscriberPaymentMethodRepository, type SubscriberPaymentMethodSetupData, type SubscriberPaymentMethodSetupMatch, type SubscriberPaymentMethodStatus, type SubscriberReadiness, type SubscriberRecord, type SubscriberRepository, type SubscriberTaxOrigin, type SubscriberTaxOriginChangeRecord, type SubscriberTaxOriginField, type SubscriberTaxOriginValues, type SubscriberTaxStatus, type SubscriberVatIdCheckRecord, type SubscriberVatIdCheckResult, type SubscriberWithCurrentCheck, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractParties, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionNotice, type SubscriptionNoticeDelivery, type SubscriptionNoticeKey, type SubscriptionNoticeKind, type SubscriptionNoticePort, type SubscriptionNoticeRecord, type SubscriptionNoticeRepository, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SupersedeSubscriptionContractData, type SyncDiscoveryResult, TAX_ERROR_CODES, TAX_TREATMENT_KINDS, type TaxAdapter, type TaxAdapterFactory, type TaxAdapterIdentity, type TaxDecision, type TaxDecisionRequest, type TaxErrorCode, type TaxIssuer, type TaxOriginWrite, type TaxTreatment, type TaxTreatmentKind, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionUsage, 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, VERSION_RETIREMENT_CAPABILITY, type VatIdCheck, type VatIdCheckOutcome, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionOffer, type VersionOfferClass, type VersionOfferFields, type VersionOfferSide, type VersionOfferView, type VersionOfferedNotice, type VersionRetiredNotice, type VersionRetirementRecord, type VersionRetirementReminder, type VersionRetirementRepository, type VersionRetirementView, type VersionSale, type VersionSaleDates, type VersionSaleKind, type VersionSwitchResult, type VersionWindow, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleKeyTaken, bundleStemDefaults, canonicalJson, canonicalVatId, catalogDraftExists, catalogVersionAlreadyPublished, catalogVersionGone, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, classifyVersionOffer, collectUnsatisfiedRequires, computeIncludedVat, concurrencyGate, concurrencyGateOf, contractPartiesOf, coverageExcludingSelf, customLimitsReader, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, grossFromNet, identityCorrectionDelta, isBundleRedundant, isForeignPaymentMethodReferenceError, isMaintenanceAnnouncementLapsed, isMaintenanceOverrun, isPaymentCallbackRejectedError, isPersistenceRefusal, isPlatformUserExistsError, isVersionActiveAt, isVersionEditable, issuerIdentityOf, keepOneRecommended, keepsVatIdCheck, maintenanceRetryAfterSeconds, maintenanceStatusOf, maintenanceWindowStatusOf, maintenanceWindowViewOf, marketingProjectionTaken, membersLeftOut, missingRequiresFor, movedIdentityFields, netFromGross, noActivePlanVersion, parseZonedInstant, percentOf, pickActivePromo, planCatalogSettingsOf, planKeyTaken, planNotInCatalog, previousUtcDay, promoCodeTaken, promoStatus, promotionOnPrice, prorate, readCustomLimits, readQuotaRecord, readQuotaValue, recordedIssuerIdentity, refuseForeignPaymentMethodReference, resolveBundleAvailability, resolveErrorMessage, retirementCostsTheSubscription, retirementReminderDueAt, retirementReminderIsDue, retirementSwitchTerms, roundToCents, sameLegalIdentity, scheduledChangeAfterWrite, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberChargeColumns, subscriberFromRegistration, subscriberPaymentMethodColumns, subscriptionBundleAlreadyCancelled, subscriptionBundleGone, subscriptionContractGone, subscriptionGone, sumToCents, taxOriginOf, taxOriginWrite, taxTreatmentToJson, toBundleStemRow, toBundleVersionRetirementRecord, toCents, toContractLineItemRecord, toDecimalString, toMaintenanceWindowRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberChargeRecord, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriberTaxOriginChangeRecord, toSubscriberVatIdCheckRecord, toSubscriptionBundleRecord, toSubscriptionContractRecord, toSubscriptionNoticeRecord, toTaxOriginValues, toTaxTreatment, toVersionRetirementRecord, vatIdCheckFromStore, versionOnSale, versionOnSaleOrNext, versionSale };