@saasicat/nest 1.0.0-rc.21 → 1.0.0-rc.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/_entries.cjs +15561 -12478
  3. package/dist/admin/index.d.cts +4 -4
  4. package/dist/admin/index.d.ts +4 -4
  5. package/dist/admin/index.js +8 -5
  6. package/dist/{admin-resources.module-CWqdI9BV.d.ts → admin-resources.module-DtWAFI-G.d.ts} +1 -1
  7. package/dist/{admin-resources.module-B4XNvdH-.d.cts → admin-resources.module-pS7LbdbI.d.cts} +1 -1
  8. package/dist/{admin-stats.service-CsLNt19Z.d.ts → admin-stats.service--1sRNpUx.d.ts} +2 -2
  9. package/dist/{admin-stats.service-DrZrU8IJ.d.cts → admin-stats.service-ChATI9YK.d.cts} +2 -2
  10. package/dist/{aggregation-ChpZDh0g.d.ts → aggregation-B8iZBesJ.d.ts} +63 -4
  11. package/dist/{aggregation-OpnhwzF5.d.cts → aggregation-BRzgRXDb.d.cts} +63 -4
  12. package/dist/billing/index.d.cts +280 -13
  13. package/dist/billing/index.d.ts +280 -13
  14. package/dist/billing/index.js +32 -8
  15. package/dist/catalog/index.d.cts +2 -2
  16. package/dist/catalog/index.d.ts +2 -2
  17. package/dist/catalog/index.js +4 -2
  18. package/dist/{catalog.module-T-I5Ricz.d.cts → catalog.module-CeKslGHW.d.cts} +1 -1
  19. package/dist/{catalog.module-C9O7BxRq.d.ts → catalog.module-CiurcIjI.d.ts} +1 -1
  20. package/dist/checkout-offer/index.d.cts +4 -4
  21. package/dist/checkout-offer/index.d.ts +4 -4
  22. package/dist/checkout-offer/index.js +5 -5
  23. package/dist/{checkout-offer.module-x7SP_dX4.d.ts → checkout-offer.module-C761mcEv.d.ts} +1 -1
  24. package/dist/{checkout-offer.module-DFhGy6JO.d.cts → checkout-offer.module-CSHB4bB8.d.cts} +1 -1
  25. package/dist/{checkout-offer.service-BeHgYikI.d.ts → checkout-offer.service-Dux8EgEM.d.ts} +3 -3
  26. package/dist/{checkout-offer.service-CCVxG9b2.d.cts → checkout-offer.service-HKoTZ3JH.d.cts} +3 -3
  27. package/dist/{chunk-F5X66HF5.js → chunk-2ECX7BST.js} +1 -1
  28. package/dist/{chunk-G6EZWECL.js → chunk-2XBWYMOL.js} +141 -26
  29. package/dist/{chunk-R5YCJBHY.js → chunk-3HBP2HK3.js} +6 -2
  30. package/dist/{chunk-S33SO5XX.js → chunk-4OFJLVVH.js} +4 -0
  31. package/dist/{chunk-AOS2JPDD.js → chunk-5LL2554P.js} +757 -163
  32. package/dist/chunk-5MZH3VVU.js +292 -0
  33. package/dist/{chunk-WHJSYKNC.js → chunk-7LHUENAT.js} +2 -2
  34. package/dist/{chunk-M47BNEY2.js → chunk-7MLB6T5B.js} +2072 -407
  35. package/dist/{chunk-NDLC5GYK.js → chunk-CVCKXKGT.js} +138 -21
  36. package/dist/{chunk-VBRYPU7V.js → chunk-E224LKO2.js} +3 -1
  37. package/dist/{chunk-QPVDCKYS.js → chunk-ESEWSAOV.js} +4 -3
  38. package/dist/{chunk-CQ2ZZMTD.js → chunk-MU4O4EKX.js} +711 -828
  39. package/dist/{chunk-JBCC6C3M.js → chunk-NQIPQI2Q.js} +26 -7
  40. package/dist/{chunk-4SDSYV4A.js → chunk-PBL7N5J3.js} +18 -2
  41. package/dist/{chunk-LLYVYRGJ.js → chunk-QTJEZDKC.js} +15 -275
  42. package/dist/{chunk-3RLWML2S.js → chunk-QWKBOLBH.js} +35 -0
  43. package/dist/{chunk-XSSWYPP5.js → chunk-TR3L6FRF.js} +6 -2
  44. package/dist/chunk-TSLGMPGZ.js +21 -0
  45. package/dist/chunk-UJZCESIC.js +466 -0
  46. package/dist/{chunk-TOEFN7DN.js → chunk-W6VNCMOQ.js} +3 -3
  47. package/dist/{chunk-7NJKVC5X.js → chunk-WQNOCOI2.js} +53 -6
  48. package/dist/chunk-YZSILFW4.js +142 -0
  49. package/dist/{chunk-55QEDAMX.js → chunk-ZCXW24NH.js} +4 -9
  50. package/dist/discovery/index.js +2 -1
  51. package/dist/{enforce-quota.interceptor-BFyVdWe8.d.cts → enforce-quota.interceptor-Dc-1_zQf.d.cts} +2 -2
  52. package/dist/{enforce-quota.interceptor-GaBXboGx.d.ts → enforce-quota.interceptor-MXpwsOJ2.d.ts} +2 -2
  53. package/dist/entitlement/index.d.cts +1 -1
  54. package/dist/entitlement/index.d.ts +1 -1
  55. package/dist/entitlement/index.js +5 -3
  56. package/dist/index.d.cts +62 -25
  57. package/dist/index.d.ts +62 -25
  58. package/dist/index.js +81 -26
  59. package/dist/{issuer-identity.check-CBO0vcsq.d.cts → issuer-identity.check-BrZXesOF.d.cts} +3 -3
  60. package/dist/{issuer-identity.check-Cz9CEMkZ.d.ts → issuer-identity.check-BzlFSmSZ.d.ts} +3 -3
  61. package/dist/maintenance.service-CNMI3tSm.d.cts +133 -0
  62. package/dist/maintenance.service-yx6fxjUj.d.ts +133 -0
  63. package/dist/{module-options-DmQ3G4sZ.d.ts → module-options-BSYxlA38.d.ts} +50 -9
  64. package/dist/{module-options-qAOwinHR.d.cts → module-options-BkufuqlM.d.cts} +50 -9
  65. package/dist/payments/index.d.cts +2 -2
  66. package/dist/payments/index.d.ts +2 -2
  67. package/dist/payments/index.js +2 -2
  68. package/dist/{payments.module-BdUq9ot_.d.cts → payments.module-CwLeaflk.d.cts} +1 -1
  69. package/dist/{payments.module-CQGv_VG7.d.ts → payments.module-DmIN-HWx.d.ts} +1 -1
  70. package/dist/{plan-versions.service-DARLh-qI.d.cts → plan-versions.service-2mD0iEvY.d.cts} +1 -1
  71. package/dist/{plan-versions.service-C0N-Em2W.d.ts → plan-versions.service-C4a9aCEU.d.ts} +1 -1
  72. package/dist/platform/index.d.cts +34 -25
  73. package/dist/platform/index.d.ts +34 -25
  74. package/dist/platform/index.js +22 -17
  75. package/dist/promo/index.d.cts +15 -5
  76. package/dist/promo/index.d.ts +15 -5
  77. package/dist/promo/index.js +9 -3
  78. package/dist/{promo.module-CKkECmU8.d.cts → promo.module-Ddx-swUV.d.cts} +1 -1
  79. package/dist/{promo.module-DuIJdK3U.d.ts → promo.module-PsIvDcUp.d.ts} +1 -1
  80. package/dist/{promo.service-BYBu6dy3.d.cts → promo.service-BextPvx5.d.cts} +23 -1
  81. package/dist/{promo.service-CFjfF0Xm.d.ts → promo.service-Dqqh0JXn.d.ts} +23 -1
  82. package/dist/registration/index.d.cts +7 -4
  83. package/dist/registration/index.d.ts +7 -4
  84. package/dist/registration/index.js +11 -6
  85. package/dist/subscription-contract/index.d.cts +13 -3
  86. package/dist/subscription-contract/index.d.ts +13 -3
  87. package/dist/subscription-contract/index.js +5 -3
  88. package/dist/{subscription-contract.module-BfIRpc1o.d.ts → subscription-contract.module-B5wrmzkz.d.ts} +8 -1
  89. package/dist/{subscription-contract.module-DTMuUJYd.d.cts → subscription-contract.module-qaswPXwT.d.cts} +8 -1
  90. package/dist/{subscription-contract.service-CfNApLuP.d.cts → subscription-contract.service-CH2TKw-j.d.cts} +45 -3
  91. package/dist/{subscription-contract.service-CPZrTM9C.d.ts → subscription-contract.service-Dm2xEFZi.d.ts} +45 -3
  92. package/dist/{tenant-billing.controller-BLqbsONe.d.ts → tenant-billing.controller-BMH9YODT.d.ts} +92 -11
  93. package/dist/{tenant-billing.controller-DKbAqTbM.d.cts → tenant-billing.controller-BX3VExL3.d.cts} +92 -11
  94. package/dist/{tenant-billing.module-ClbjzocC.d.cts → tenant-billing.module-Do3QyKbr.d.cts} +33 -3
  95. package/dist/{tenant-billing.module-DohgJJ2m.d.ts → tenant-billing.module-W5_Y4ogN.d.ts} +33 -3
  96. package/dist/{tenant-billing.tokens-G-1xOlMr.d.cts → tenant-billing.tokens-D0vr1lfj.d.cts} +1 -1
  97. package/dist/{tenant-billing.tokens-G-1xOlMr.d.ts → tenant-billing.tokens-D0vr1lfj.d.ts} +1 -1
  98. package/dist/testing/index.d.cts +14 -13
  99. package/dist/testing/index.d.ts +14 -13
  100. package/dist/testing/index.js +54 -35
  101. package/package.json +5 -3
@@ -1,8 +1,8 @@
1
- import { f as AdminStatsService, g as AdminStatsSnapshot } from '../admin-stats.service-DrZrU8IJ.cjs';
2
- export { A as AdminBypassRlsInterceptor, a as AdminManifestModule, b as AdminManifestModuleOptions, c as AdminManifestService, d as AdminModule, e as AdminModuleOptions, h as MfaGuard, M as MfaService, P as PLATFORM_CORE_CONTRIBUTION_TOKEN, R as REQUIRE_MFA_KEY, i as RequireMfa, S as SuperAdminGuard, T as TotpSetupResult, V as VerifyTotpInput } from '../admin-stats.service-DrZrU8IJ.cjs';
1
+ import { f as AdminStatsService, h as AdminStatsSnapshot } from '../admin-stats.service-ChATI9YK.cjs';
2
+ export { A as AdminBypassRlsInterceptor, a as AdminManifestModule, b as AdminManifestModuleOptions, c as AdminManifestService, d as AdminModule, e as AdminModuleOptions, g as MfaGuard, M as MfaService, P as PLATFORM_CORE_CONTRIBUTION_TOKEN, R as REQUIRE_MFA_KEY, i as RequireMfa, S as SuperAdminGuard, T as TotpSetupResult, V as VerifyTotpInput } from '../admin-stats.service-ChATI9YK.cjs';
3
3
  export { A as AdminAuditService } from '../admin-audit.service-4P3Djdxk.cjs';
4
- import { b as AdminManifestConfig } from '../admin-resources.module-B4XNvdH-.cjs';
5
- export { c as ADMIN_MANIFEST_CONFIG, d as ADMIN_RESOURCES_PORT_TOKEN, e as AdminResourcesModule, A as AdminResourcesModuleOptions, f as AdminResourcesService, g as AdminStatsModule, a as AdminStatsModuleOptions, S as SuspendTenantDto } from '../admin-resources.module-B4XNvdH-.cjs';
4
+ import { b as AdminManifestConfig } from '../admin-resources.module-pS7LbdbI.cjs';
5
+ export { e as ADMIN_MANIFEST_CONFIG, f as ADMIN_RESOURCES_PORT_TOKEN, g as AdminResourcesModule, A as AdminResourcesModuleOptions, c as AdminResourcesService, d as AdminStatsModule, a as AdminStatsModuleOptions, S as SuspendTenantDto } from '../admin-resources.module-pS7LbdbI.cjs';
6
6
  import { PublicBootResponse, ManifestContribution } from '@saasicat/core';
7
7
  import { Type, CanActivate } from '@nestjs/common';
8
8
  import '@nestjs/core';
@@ -1,8 +1,8 @@
1
- import { f as AdminStatsService, g as AdminStatsSnapshot } from '../admin-stats.service-CsLNt19Z.js';
2
- export { A as AdminBypassRlsInterceptor, a as AdminManifestModule, b as AdminManifestModuleOptions, c as AdminManifestService, d as AdminModule, e as AdminModuleOptions, h as MfaGuard, M as MfaService, P as PLATFORM_CORE_CONTRIBUTION_TOKEN, R as REQUIRE_MFA_KEY, i as RequireMfa, S as SuperAdminGuard, T as TotpSetupResult, V as VerifyTotpInput } from '../admin-stats.service-CsLNt19Z.js';
1
+ import { f as AdminStatsService, h as AdminStatsSnapshot } from '../admin-stats.service--1sRNpUx.js';
2
+ export { A as AdminBypassRlsInterceptor, a as AdminManifestModule, b as AdminManifestModuleOptions, c as AdminManifestService, d as AdminModule, e as AdminModuleOptions, g as MfaGuard, M as MfaService, P as PLATFORM_CORE_CONTRIBUTION_TOKEN, R as REQUIRE_MFA_KEY, i as RequireMfa, S as SuperAdminGuard, T as TotpSetupResult, V as VerifyTotpInput } from '../admin-stats.service--1sRNpUx.js';
3
3
  export { A as AdminAuditService } from '../admin-audit.service-4P3Djdxk.js';
4
- import { b as AdminManifestConfig } from '../admin-resources.module-CWqdI9BV.js';
5
- export { c as ADMIN_MANIFEST_CONFIG, d as ADMIN_RESOURCES_PORT_TOKEN, e as AdminResourcesModule, A as AdminResourcesModuleOptions, f as AdminResourcesService, g as AdminStatsModule, a as AdminStatsModuleOptions, S as SuspendTenantDto } from '../admin-resources.module-CWqdI9BV.js';
4
+ import { b as AdminManifestConfig } from '../admin-resources.module-DtWAFI-G.js';
5
+ export { e as ADMIN_MANIFEST_CONFIG, f as ADMIN_RESOURCES_PORT_TOKEN, g as AdminResourcesModule, A as AdminResourcesModuleOptions, c as AdminResourcesService, d as AdminStatsModule, a as AdminStatsModuleOptions, S as SuspendTenantDto } from '../admin-resources.module-DtWAFI-G.js';
6
6
  import { PublicBootResponse, ManifestContribution } from '@saasicat/core';
7
7
  import { Type, CanActivate } from '@nestjs/common';
8
8
  import '@nestjs/core';
@@ -1,7 +1,6 @@
1
1
  import "../chunk-UF53DWWR.js";
2
2
  import {
3
3
  ADMIN_MANIFEST_CONFIG,
4
- ADMIN_RESOURCES_PORT_TOKEN,
5
4
  ADMIN_STATS_AUDIT_WINDOW_DAYS_TOKEN,
6
5
  AUDIT_STATS_PORT_TOKEN,
7
6
  AdminBypassRlsInterceptor,
@@ -9,8 +8,6 @@ import {
9
8
  AdminManifestService,
10
9
  AdminModule,
11
10
  AdminPublicBootController,
12
- AdminResourcesModule,
13
- AdminResourcesService,
14
11
  AdminStatsController,
15
12
  AdminStatsModule,
16
13
  AdminStatsService,
@@ -19,9 +16,14 @@ import {
19
16
  PROMO_CODE_STATS_PORT_TOKEN,
20
17
  SUBSCRIPTION_STATS_PORT_TOKEN,
21
18
  SuperAdminGuard,
22
- SuspendTenantDto,
23
19
  buildAdminStatsController
24
- } from "../chunk-LLYVYRGJ.js";
20
+ } from "../chunk-QTJEZDKC.js";
21
+ import {
22
+ ADMIN_RESOURCES_PORT_TOKEN,
23
+ AdminResourcesModule,
24
+ AdminResourcesService,
25
+ SuspendTenantDto
26
+ } from "../chunk-5MZH3VVU.js";
25
27
  import {
26
28
  MfaGuard,
27
29
  MfaService,
@@ -31,6 +33,7 @@ import {
31
33
  import {
32
34
  AdminAuditService
33
35
  } from "../chunk-OOTEXP47.js";
36
+ import "../chunk-TSLGMPGZ.js";
34
37
  import {
35
38
  AUDIT_PORT_TOKEN,
36
39
  MFA_PORT_TOKEN,
@@ -62,4 +62,4 @@ declare class AdminResourcesModule {
62
62
  static forRoot(options: AdminResourcesModuleOptions): DynamicModule;
63
63
  }
64
64
 
65
- export { type AdminResourcesModuleOptions as A, SuspendTenantDto as S, type AdminStatsModuleOptions as a, type AdminManifestConfig as b, ADMIN_MANIFEST_CONFIG as c, ADMIN_RESOURCES_PORT_TOKEN as d, AdminResourcesModule as e, AdminResourcesService as f, AdminStatsModule as g };
65
+ export { type AdminResourcesModuleOptions as A, SuspendTenantDto as S, type AdminStatsModuleOptions as a, type AdminManifestConfig as b, AdminResourcesService as c, AdminStatsModule as d, ADMIN_MANIFEST_CONFIG as e, ADMIN_RESOURCES_PORT_TOKEN as f, AdminResourcesModule as g };
@@ -62,4 +62,4 @@ declare class AdminResourcesModule {
62
62
  static forRoot(options: AdminResourcesModuleOptions): DynamicModule;
63
63
  }
64
64
 
65
- export { type AdminResourcesModuleOptions as A, SuspendTenantDto as S, type AdminStatsModuleOptions as a, type AdminManifestConfig as b, ADMIN_MANIFEST_CONFIG as c, ADMIN_RESOURCES_PORT_TOKEN as d, AdminResourcesModule as e, AdminResourcesService as f, AdminStatsModule as g };
65
+ export { type AdminResourcesModuleOptions as A, SuspendTenantDto as S, type AdminStatsModuleOptions as a, type AdminManifestConfig as b, AdminResourcesService as c, AdminStatsModule as d, ADMIN_MANIFEST_CONFIG as e, ADMIN_RESOURCES_PORT_TOKEN as f, AdminResourcesModule as g };
@@ -4,7 +4,7 @@ import { MfaPort, RlsBypassPort, AuditPort, ManifestContribution, AdminManifest,
4
4
  import { Observable } from 'rxjs';
5
5
  import { P as ProviderSpec } from './di-CcNeq9v-.js';
6
6
  import { P as PlanCatalogSource } from './plan-catalog-source-DWe-BGY1.js';
7
- import { b as AdminManifestConfig } from './admin-resources.module-CWqdI9BV.js';
7
+ import { b as AdminManifestConfig } from './admin-resources.module-DtWAFI-G.js';
8
8
 
9
9
  declare class SuperAdminGuard implements CanActivate {
10
10
  canActivate(context: ExecutionContext): boolean;
@@ -181,4 +181,4 @@ declare class AdminStatsService {
181
181
  getSnapshot(): Promise<AdminStatsSnapshot>;
182
182
  }
183
183
 
184
- export { AdminBypassRlsInterceptor as A, MfaService as M, PLATFORM_CORE_CONTRIBUTION_TOKEN as P, REQUIRE_MFA_KEY as R, SuperAdminGuard as S, type TotpSetupResult as T, type VerifyTotpInput as V, AdminManifestModule as a, type AdminManifestModuleOptions as b, AdminManifestService as c, AdminModule as d, type AdminModuleOptions as e, AdminStatsService as f, type AdminStatsSnapshot as g, MfaGuard as h, RequireMfa as i };
184
+ export { AdminBypassRlsInterceptor as A, MfaService as M, PLATFORM_CORE_CONTRIBUTION_TOKEN as P, REQUIRE_MFA_KEY as R, SuperAdminGuard as S, type TotpSetupResult as T, type VerifyTotpInput as V, AdminManifestModule as a, type AdminManifestModuleOptions as b, AdminManifestService as c, AdminModule as d, type AdminModuleOptions as e, AdminStatsService as f, MfaGuard as g, type AdminStatsSnapshot as h, RequireMfa as i };
@@ -4,7 +4,7 @@ import { MfaPort, RlsBypassPort, AuditPort, ManifestContribution, AdminManifest,
4
4
  import { Observable } from 'rxjs';
5
5
  import { P as ProviderSpec } from './di-CcNeq9v-.cjs';
6
6
  import { P as PlanCatalogSource } from './plan-catalog-source-DWe-BGY1.cjs';
7
- import { b as AdminManifestConfig } from './admin-resources.module-B4XNvdH-.cjs';
7
+ import { b as AdminManifestConfig } from './admin-resources.module-pS7LbdbI.cjs';
8
8
 
9
9
  declare class SuperAdminGuard implements CanActivate {
10
10
  canActivate(context: ExecutionContext): boolean;
@@ -181,4 +181,4 @@ declare class AdminStatsService {
181
181
  getSnapshot(): Promise<AdminStatsSnapshot>;
182
182
  }
183
183
 
184
- export { AdminBypassRlsInterceptor as A, MfaService as M, PLATFORM_CORE_CONTRIBUTION_TOKEN as P, REQUIRE_MFA_KEY as R, SuperAdminGuard as S, type TotpSetupResult as T, type VerifyTotpInput as V, AdminManifestModule as a, type AdminManifestModuleOptions as b, AdminManifestService as c, AdminModule as d, type AdminModuleOptions as e, AdminStatsService as f, type AdminStatsSnapshot as g, MfaGuard as h, RequireMfa as i };
184
+ export { AdminBypassRlsInterceptor as A, MfaService as M, PLATFORM_CORE_CONTRIBUTION_TOKEN as P, REQUIRE_MFA_KEY as R, SuperAdminGuard as S, type TotpSetupResult as T, type VerifyTotpInput as V, AdminManifestModule as a, type AdminManifestModuleOptions as b, AdminManifestService as c, AdminModule as d, type AdminModuleOptions as e, AdminStatsService as f, MfaGuard as g, type AdminStatsSnapshot as h, RequireMfa as i };
@@ -88,6 +88,16 @@ interface EffectiveLimitsSnapshot {
88
88
  features: FeatureKey[];
89
89
  }
90
90
 
91
+ /** What a contract frozen at a moment records as its entitlements. */
92
+ interface ContractLimits {
93
+ limits: EffectiveLimits;
94
+ /**
95
+ * The add-ons left out of `limits` because their cancellation is declared.
96
+ * The contract names them in its snapshot, so that their bookings grant
97
+ * them until their effective date and a reader knows the snapshot does not.
98
+ */
99
+ leftOutBundleVersionIds: string[];
100
+ }
91
101
  interface EnforceLimitInput<T> {
92
102
  /** Tenant whose subscription is checked. */
93
103
  tenantId: string;
@@ -135,6 +145,41 @@ declare class EntitlementService {
135
145
  * older than the one everybody else should be answered from.
136
146
  */
137
147
  computeLimits(tenantId: string, now?: Date, catalog?: PlanCatalog): Promise<EffectiveLimits>;
148
+ /**
149
+ * What a contract frozen at `now` records as its entitlements: what
150
+ * `computeLimits` would grant with no contract in force, less the add-ons
151
+ * whose cancellation is declared. The contract in force is not read, so a
152
+ * successor can be composed — and shown — before the one it replaces ends.
153
+ *
154
+ * Those are granted until their effective date by the booking rather than
155
+ * by the contract (`mergeSubscriptionBundlesIntoLimits`), so their end
156
+ * needs nobody to write the contract again. Frozen into the snapshot, they
157
+ * would be granted for as long as the contract runs. Never cached, like
158
+ * `computeLimits` with a catalogue.
159
+ */
160
+ computeContractLimits(tenantId: string, now: Date, catalog: PlanCatalog): Promise<ContractLimits>;
161
+ /**
162
+ * The features a contract of the tenant covering exactly `bundleVersionIds`
163
+ * records when frozen now, and the plan version they are read from — or
164
+ * `null` where the tenant has no subscription. They are the plan version
165
+ * the subscription is bound to and those add-on versions, each as its row
166
+ * reads today, with the subscription's own arrangement — aliased and
167
+ * filtered the way every grant is.
168
+ *
169
+ * The add-ons are the ones the caller names, not the bookings running now:
170
+ * a vocabulary carried into a contract changes what the add-ons it already
171
+ * covers are called, not which add-ons it covers. Quotas are not asked
172
+ * for, for the same reason.
173
+ */
174
+ contractFeaturesFor(tenantId: string, bundleVersionIds: Iterable<string>, catalog: PlanCatalog): Promise<{
175
+ planVersionId: string;
176
+ features: Set<string>;
177
+ } | null>;
178
+ /**
179
+ * `features` with every successor a `replaces` declaration carries them to —
180
+ * what a contract holding them is granted beyond its own keys.
181
+ */
182
+ withReplacements(features: ReadonlySet<string>): Set<string>;
138
183
  /**
139
184
  * Clears a tenant's cache entry. MUST be called as soon as a mutation
140
185
  * changes the subscription, a bundle booking, or a PlanVersion binding —
@@ -149,13 +194,14 @@ declare class EntitlementService {
149
194
  * have a `SubscriptionRecord` (e.g. within a transaction).
150
195
  */
151
196
  deriveLimits(sub: SubscriptionRecord, now: Date, tx?: TransactionContext): Promise<EffectiveLimits>;
197
+ private requireSubscription;
152
198
  /**
153
199
  * `deriveLimits` against a catalogue already read. The catalogue decides
154
200
  * which features are `plannedOnly`, and it is read outside any transaction
155
201
  * a caller holds, so that checking a limit does not wait for a second
156
202
  * connection while the subscription row is locked.
157
203
  */
158
- private limitsFor;
204
+ private answerFor;
159
205
  /**
160
206
  * The last thing every path does, so that no path can skip it.
161
207
  *
@@ -208,6 +254,11 @@ declare class EntitlementService {
208
254
  * Spec:
209
255
  */
210
256
  declare function filterActiveSubscriptionBundles(bundles: readonly SubscriptionBundleSnapshot[], now: Date): SubscriptionBundleSnapshot[];
257
+ /**
258
+ * Whether a booking's end is already set. Such a booking is still active until
259
+ * that date, but it is not part of what a contract agrees to from here on.
260
+ */
261
+ declare function isCancellationDeclared(booking: Pick<SubscriptionBundleSnapshot, 'canceledEffectiveAt'>): boolean;
211
262
  /**
212
263
  * Aggregates the quotas of all active SubscriptionBundle bookings:
213
264
  * Σ per QuotaKey, `-1` (unlimited) dominates. Bundle features +
@@ -232,9 +283,17 @@ declare function aggregateContractLineItemEntitlements(lineItems: readonly Pick<
232
283
  declare function contractLimits(contract: Pick<SubscriptionContractRecord, 'entitlementSnapshot' | 'lineItems'>): EffectiveLimits;
233
284
  /**
234
285
  * `BundleVersion`s the contract already accounts for — from the freeze
235
- * (`originalBundleVersionIds`) and from its bundle line items.
286
+ * (`originalBundleVersionIds`) and from its bundle line items — less the ones
287
+ * its entitlement snapshot says it left out.
288
+ *
289
+ * A contract written while an add-on's cancellation is declared keeps the
290
+ * add-on's line, because it is billed until its effective date, but leaves its
291
+ * features and quotas out of the snapshot and names it there. Such an add-on is
292
+ * not covered: its booking grants it until that date, and nothing does after.
293
+ * A snapshot that names nothing — written earlier, or by an application —
294
+ * covers every add-on its contract lists, so nothing is counted twice.
236
295
  */
237
- declare function contractBundleVersionIds(contract: Pick<SubscriptionContractRecord, 'originalBundleVersionIds' | 'lineItems'>): Set<string>;
296
+ declare function contractBundleVersionIds(contract: Pick<SubscriptionContractRecord, 'originalBundleVersionIds' | 'lineItems' | 'entitlementSnapshot'>): Set<string>;
238
297
  /**
239
298
  * Adds bundle bookings on top of limits that came from a contract.
240
299
  *
@@ -290,4 +349,4 @@ declare function hasAnyFeature(limits: EffectiveLimits, features: readonly Featu
290
349
  */
291
350
  declare function toEffectiveLimitsSnapshot(limits: EffectiveLimits): EffectiveLimitsSnapshot;
292
351
 
293
- export { type CustomLimitsShape as C, type EffectiveLimits as E, type PlanVersionSnapshot as P, type SubscriptionBundleSnapshot as S, type EffectiveLimitsSnapshot as a, type EnforceLimitInput as b, EntitlementService as c, type SubscriptionLimitsInput as d, aggregateContractLineItemEntitlements as e, aggregateLimits as f, aggregateSubscriptionBundleQuotas as g, applyCustomLimits as h, collectSubscriptionBundleFeatures as i, contractBundleVersionIds as j, contractLimits as k, filterActiveSubscriptionBundles as l, filterPlannedOnlyFeatures as m, hasAnyFeature as n, hasFeature as o, mergeSubscriptionBundlesIntoLimits as p, toEffectiveLimitsSnapshot as t };
352
+ export { type ContractLimits as C, EntitlementService as E, type PlanVersionSnapshot as P, type SubscriptionBundleSnapshot as S, type EffectiveLimitsSnapshot as a, type CustomLimitsShape as b, type EffectiveLimits as c, type EnforceLimitInput as d, type SubscriptionLimitsInput as e, aggregateContractLineItemEntitlements as f, aggregateLimits as g, aggregateSubscriptionBundleQuotas as h, applyCustomLimits as i, collectSubscriptionBundleFeatures as j, contractBundleVersionIds as k, contractLimits as l, filterActiveSubscriptionBundles as m, filterPlannedOnlyFeatures as n, hasAnyFeature as o, hasFeature as p, isCancellationDeclared as q, mergeSubscriptionBundlesIntoLimits as r, toEffectiveLimitsSnapshot as t };
@@ -88,6 +88,16 @@ interface EffectiveLimitsSnapshot {
88
88
  features: FeatureKey[];
89
89
  }
90
90
 
91
+ /** What a contract frozen at a moment records as its entitlements. */
92
+ interface ContractLimits {
93
+ limits: EffectiveLimits;
94
+ /**
95
+ * The add-ons left out of `limits` because their cancellation is declared.
96
+ * The contract names them in its snapshot, so that their bookings grant
97
+ * them until their effective date and a reader knows the snapshot does not.
98
+ */
99
+ leftOutBundleVersionIds: string[];
100
+ }
91
101
  interface EnforceLimitInput<T> {
92
102
  /** Tenant whose subscription is checked. */
93
103
  tenantId: string;
@@ -135,6 +145,41 @@ declare class EntitlementService {
135
145
  * older than the one everybody else should be answered from.
136
146
  */
137
147
  computeLimits(tenantId: string, now?: Date, catalog?: PlanCatalog): Promise<EffectiveLimits>;
148
+ /**
149
+ * What a contract frozen at `now` records as its entitlements: what
150
+ * `computeLimits` would grant with no contract in force, less the add-ons
151
+ * whose cancellation is declared. The contract in force is not read, so a
152
+ * successor can be composed — and shown — before the one it replaces ends.
153
+ *
154
+ * Those are granted until their effective date by the booking rather than
155
+ * by the contract (`mergeSubscriptionBundlesIntoLimits`), so their end
156
+ * needs nobody to write the contract again. Frozen into the snapshot, they
157
+ * would be granted for as long as the contract runs. Never cached, like
158
+ * `computeLimits` with a catalogue.
159
+ */
160
+ computeContractLimits(tenantId: string, now: Date, catalog: PlanCatalog): Promise<ContractLimits>;
161
+ /**
162
+ * The features a contract of the tenant covering exactly `bundleVersionIds`
163
+ * records when frozen now, and the plan version they are read from — or
164
+ * `null` where the tenant has no subscription. They are the plan version
165
+ * the subscription is bound to and those add-on versions, each as its row
166
+ * reads today, with the subscription's own arrangement — aliased and
167
+ * filtered the way every grant is.
168
+ *
169
+ * The add-ons are the ones the caller names, not the bookings running now:
170
+ * a vocabulary carried into a contract changes what the add-ons it already
171
+ * covers are called, not which add-ons it covers. Quotas are not asked
172
+ * for, for the same reason.
173
+ */
174
+ contractFeaturesFor(tenantId: string, bundleVersionIds: Iterable<string>, catalog: PlanCatalog): Promise<{
175
+ planVersionId: string;
176
+ features: Set<string>;
177
+ } | null>;
178
+ /**
179
+ * `features` with every successor a `replaces` declaration carries them to —
180
+ * what a contract holding them is granted beyond its own keys.
181
+ */
182
+ withReplacements(features: ReadonlySet<string>): Set<string>;
138
183
  /**
139
184
  * Clears a tenant's cache entry. MUST be called as soon as a mutation
140
185
  * changes the subscription, a bundle booking, or a PlanVersion binding —
@@ -149,13 +194,14 @@ declare class EntitlementService {
149
194
  * have a `SubscriptionRecord` (e.g. within a transaction).
150
195
  */
151
196
  deriveLimits(sub: SubscriptionRecord, now: Date, tx?: TransactionContext): Promise<EffectiveLimits>;
197
+ private requireSubscription;
152
198
  /**
153
199
  * `deriveLimits` against a catalogue already read. The catalogue decides
154
200
  * which features are `plannedOnly`, and it is read outside any transaction
155
201
  * a caller holds, so that checking a limit does not wait for a second
156
202
  * connection while the subscription row is locked.
157
203
  */
158
- private limitsFor;
204
+ private answerFor;
159
205
  /**
160
206
  * The last thing every path does, so that no path can skip it.
161
207
  *
@@ -208,6 +254,11 @@ declare class EntitlementService {
208
254
  * Spec:
209
255
  */
210
256
  declare function filterActiveSubscriptionBundles(bundles: readonly SubscriptionBundleSnapshot[], now: Date): SubscriptionBundleSnapshot[];
257
+ /**
258
+ * Whether a booking's end is already set. Such a booking is still active until
259
+ * that date, but it is not part of what a contract agrees to from here on.
260
+ */
261
+ declare function isCancellationDeclared(booking: Pick<SubscriptionBundleSnapshot, 'canceledEffectiveAt'>): boolean;
211
262
  /**
212
263
  * Aggregates the quotas of all active SubscriptionBundle bookings:
213
264
  * Σ per QuotaKey, `-1` (unlimited) dominates. Bundle features +
@@ -232,9 +283,17 @@ declare function aggregateContractLineItemEntitlements(lineItems: readonly Pick<
232
283
  declare function contractLimits(contract: Pick<SubscriptionContractRecord, 'entitlementSnapshot' | 'lineItems'>): EffectiveLimits;
233
284
  /**
234
285
  * `BundleVersion`s the contract already accounts for — from the freeze
235
- * (`originalBundleVersionIds`) and from its bundle line items.
286
+ * (`originalBundleVersionIds`) and from its bundle line items — less the ones
287
+ * its entitlement snapshot says it left out.
288
+ *
289
+ * A contract written while an add-on's cancellation is declared keeps the
290
+ * add-on's line, because it is billed until its effective date, but leaves its
291
+ * features and quotas out of the snapshot and names it there. Such an add-on is
292
+ * not covered: its booking grants it until that date, and nothing does after.
293
+ * A snapshot that names nothing — written earlier, or by an application —
294
+ * covers every add-on its contract lists, so nothing is counted twice.
236
295
  */
237
- declare function contractBundleVersionIds(contract: Pick<SubscriptionContractRecord, 'originalBundleVersionIds' | 'lineItems'>): Set<string>;
296
+ declare function contractBundleVersionIds(contract: Pick<SubscriptionContractRecord, 'originalBundleVersionIds' | 'lineItems' | 'entitlementSnapshot'>): Set<string>;
238
297
  /**
239
298
  * Adds bundle bookings on top of limits that came from a contract.
240
299
  *
@@ -290,4 +349,4 @@ declare function hasAnyFeature(limits: EffectiveLimits, features: readonly Featu
290
349
  */
291
350
  declare function toEffectiveLimitsSnapshot(limits: EffectiveLimits): EffectiveLimitsSnapshot;
292
351
 
293
- export { type CustomLimitsShape as C, type EffectiveLimits as E, type PlanVersionSnapshot as P, type SubscriptionBundleSnapshot as S, type EffectiveLimitsSnapshot as a, type EnforceLimitInput as b, EntitlementService as c, type SubscriptionLimitsInput as d, aggregateContractLineItemEntitlements as e, aggregateLimits as f, aggregateSubscriptionBundleQuotas as g, applyCustomLimits as h, collectSubscriptionBundleFeatures as i, contractBundleVersionIds as j, contractLimits as k, filterActiveSubscriptionBundles as l, filterPlannedOnlyFeatures as m, hasAnyFeature as n, hasFeature as o, mergeSubscriptionBundlesIntoLimits as p, toEffectiveLimitsSnapshot as t };
352
+ export { type ContractLimits as C, EntitlementService as E, type PlanVersionSnapshot as P, type SubscriptionBundleSnapshot as S, type EffectiveLimitsSnapshot as a, type CustomLimitsShape as b, type EffectiveLimits as c, type EnforceLimitInput as d, type SubscriptionLimitsInput as e, aggregateContractLineItemEntitlements as f, aggregateLimits as g, aggregateSubscriptionBundleQuotas as h, applyCustomLimits as i, collectSubscriptionBundleFeatures as j, contractBundleVersionIds as k, contractLimits as l, filterActiveSubscriptionBundles as m, filterPlannedOnlyFeatures as n, hasAnyFeature as o, hasFeature as p, isCancellationDeclared as q, mergeSubscriptionBundlesIntoLimits as r, toEffectiveLimitsSnapshot as t };