@saasicat/core 1.0.0-rc.5 → 1.0.0-rc.7
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/README.md +2 -1
- package/dist/.build-stamp +1 -1
- package/dist/index.cjs +229 -12
- package/dist/index.d.cts +765 -409
- package/dist/index.d.ts +765 -409
- package/dist/index.js +217 -11
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
/** Start of day (00:00 UTC) of the moment — for day-inclusive date comparisons. */
|
|
2
2
|
declare function startOfUtcDay(date: Date): Date;
|
|
3
|
+
/**
|
|
4
|
+
* The day before `value` — how a validity window closes when its successor
|
|
5
|
+
* opens (`validUntil = successor.validFrom − 1 day`, the rule this module's
|
|
6
|
+
* header states and `startOfUtcDay` above is the reading half of).
|
|
7
|
+
*
|
|
8
|
+
* It lived as three separate expressions before 2026-08-27: one in each
|
|
9
|
+
* adapter's publish path and one in the bundle repository, all agreeing by
|
|
10
|
+
* coincidence rather than by construction. Day arithmetic rather than
|
|
11
|
+
* `− 24 * 60 * 60 * 1000`: the subtraction is only equivalent while the value
|
|
12
|
+
* is a UTC midnight, and nothing in the type says it is.
|
|
13
|
+
*/
|
|
14
|
+
declare function previousUtcDay(value: Date): Date;
|
|
3
15
|
/** `<=` upper bound for a date (structurally Prisma-compatible). */
|
|
4
16
|
interface DateAtOrBefore {
|
|
5
17
|
lte: Date;
|
|
@@ -73,256 +85,6 @@ type ActiveVersionWhereWithEndsAt = ActivePlanVersionWhereWithEndsAt;
|
|
|
73
85
|
*/
|
|
74
86
|
declare const buildActiveVersionWhere: typeof buildActivePlanVersionWhere;
|
|
75
87
|
|
|
76
|
-
type FeatureKey = string;
|
|
77
|
-
type PlanId = string;
|
|
78
|
-
type QuotaKey = string;
|
|
79
|
-
interface FeatureDef {
|
|
80
|
-
key: FeatureKey;
|
|
81
|
-
label?: string;
|
|
82
|
-
icon?: string;
|
|
83
|
-
/** CORE / ADVANCED / PRO / BUSINESS / ENTERPRISE_ONLY — convention. */
|
|
84
|
-
tier?: string;
|
|
85
|
-
plannedOnly?: boolean;
|
|
86
|
-
}
|
|
87
|
-
interface PlanDef {
|
|
88
|
-
id: PlanId;
|
|
89
|
-
name?: string;
|
|
90
|
-
tagline?: string;
|
|
91
|
-
/** false = not selectable in self-service onboarding. Default: true. */
|
|
92
|
-
marketed?: boolean;
|
|
93
|
-
/** Highlighted card in onboarding (max. 1 per catalog). */
|
|
94
|
-
popular?: boolean;
|
|
95
|
-
/** Net monthly price. null = on request. */
|
|
96
|
-
monthlyNet?: number | null;
|
|
97
|
-
/** Net total amount per year. null = monthly only. */
|
|
98
|
-
yearlyNet?: number | null;
|
|
99
|
-
/** Map quotaKey → max value. -1 = unlimited. */
|
|
100
|
-
quotas: Record<QuotaKey, number>;
|
|
101
|
-
features: FeatureKey[];
|
|
102
|
-
}
|
|
103
|
-
/** App-wide marketing configuration. */
|
|
104
|
-
interface PlanCatalogMarketing {
|
|
105
|
-
/**
|
|
106
|
-
* Allowed language pool that the app may market. First = default
|
|
107
|
-
* locale. From it, the SuperAdmin activates a subset in the marketing
|
|
108
|
-
* catalog (LocaleManager).
|
|
109
|
-
*/
|
|
110
|
-
availableLocales: string[];
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* App identity block for branding + version. Consumed by the `AdminPublicBootController`
|
|
114
|
-
* and the `AdminManifestConfigFactory`; the SuperAdmin UI (platform
|
|
115
|
-
* LoginPage, AdminLayout brand block) reads the same fields via PublicBoot.
|
|
116
|
-
*
|
|
117
|
-
* `name` = brand display name (e.g. "DemoApp", "ClubApp").
|
|
118
|
-
* `label` = tag/subtitle in the brand block (e.g. "SuperAdmin").
|
|
119
|
-
* `version` = app version string (build info).
|
|
120
|
-
* `icon` = 2-character abbreviation for the logo badge (e.g. "ma", "da").
|
|
121
|
-
* `logoUrl` = optional URL to a PNG/SVG; if set, the UI renders an <img>
|
|
122
|
-
* instead of the initials badge.
|
|
123
|
-
*/
|
|
124
|
-
interface PlanCatalogApp {
|
|
125
|
-
name: string;
|
|
126
|
-
label?: string;
|
|
127
|
-
version?: string;
|
|
128
|
-
icon?: string;
|
|
129
|
-
logoUrl?: string;
|
|
130
|
-
}
|
|
131
|
-
interface PlanCatalog {
|
|
132
|
-
schemaVersion: 1;
|
|
133
|
-
projectKey: string;
|
|
134
|
-
/** App identity (branding + version), see PlanCatalogApp. Optional. */
|
|
135
|
-
app?: PlanCatalogApp;
|
|
136
|
-
/** ISO-4217 currency code. */
|
|
137
|
-
currency: string;
|
|
138
|
-
/** VAT rate in percent. */
|
|
139
|
-
vatRate: number;
|
|
140
|
-
/** App-wide marketing configuration. Optional. */
|
|
141
|
-
marketing?: PlanCatalogMarketing;
|
|
142
|
-
features?: FeatureDef[];
|
|
143
|
-
/**
|
|
144
|
-
* Optional. When omitted, plans come exclusively from the
|
|
145
|
-
* AdminUI / DB table (Plans/PlanVersions lifecycle).
|
|
146
|
-
*/
|
|
147
|
-
plans?: PlanDef[];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Backend capability key, convention: domain.action[.action]. */
|
|
151
|
-
type CapabilityKey = string;
|
|
152
|
-
/** Frontend action-registry key. Same convention as CapabilityKey. */
|
|
153
|
-
type ActionKey = CapabilityKey;
|
|
154
|
-
/** Lookup key in the static extensions: map of the UI build. */
|
|
155
|
-
type ComponentKey = string;
|
|
156
|
-
interface AdminManifest {
|
|
157
|
-
schemaVersion: 1;
|
|
158
|
-
project: {
|
|
159
|
-
key: string;
|
|
160
|
-
displayName: string;
|
|
161
|
-
/** Tag/subtitle (e.g. "SuperAdmin"). From `saas.yaml#app.label`. */
|
|
162
|
-
label?: string;
|
|
163
|
-
/** Short abbreviation for the logo badge (e.g. "ma", "da"). From `saas.yaml#app.icon`. */
|
|
164
|
-
icon?: string;
|
|
165
|
-
logoUrl?: string;
|
|
166
|
-
environment?: 'production' | 'staging' | 'development';
|
|
167
|
-
/**
|
|
168
|
-
* Allowed locale pool from the app config (`saas.yaml`
|
|
169
|
-
* `marketing.availableLocales`). First = default..
|
|
170
|
-
*/
|
|
171
|
-
availableLocales?: string[];
|
|
172
|
-
/** Default locale; equals `availableLocales[0]`. */
|
|
173
|
-
defaultLocale?: string;
|
|
174
|
-
};
|
|
175
|
-
build: {
|
|
176
|
-
platformPackageVersion: string;
|
|
177
|
-
appVersion: string;
|
|
178
|
-
manifestHash: string;
|
|
179
|
-
};
|
|
180
|
-
planCatalogSnapshot: {
|
|
181
|
-
source: string;
|
|
182
|
-
hash: string;
|
|
183
|
-
currency: string;
|
|
184
|
-
vatRate: number;
|
|
185
|
-
features?: FeatureDef[];
|
|
186
|
-
plans: PlanDef[];
|
|
187
|
-
};
|
|
188
|
-
/** Map CapabilityKey → boolean. Manifest is never a security source. */
|
|
189
|
-
capabilities: Record<CapabilityKey, boolean>;
|
|
190
|
-
navigation: {
|
|
191
|
-
standardPages: Partial<Record<StandardPageKey, StandardPageDef>>;
|
|
192
|
-
projectPages?: ProjectPageDef[];
|
|
193
|
-
};
|
|
194
|
-
dashboard?: {
|
|
195
|
-
kpiCards?: KpiCardDef[];
|
|
196
|
-
};
|
|
197
|
-
tenants?: {
|
|
198
|
-
columns?: TenantColumnDef[];
|
|
199
|
-
actions?: TenantActionDef[];
|
|
200
|
-
};
|
|
201
|
-
audit?: {
|
|
202
|
-
actions?: AuditActionDef[];
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
type StandardPageKey = 'dashboard' | 'tenants' | 'subscriptions' | 'promoCodes' | 'plans' | 'audit' | 'users' | 'pilots' | 'discovery' | 'bundles' | 'marketingCatalog' | 'platformEmail' | 'platformEmailHistory';
|
|
206
|
-
interface StandardPageDef {
|
|
207
|
-
enabled: boolean;
|
|
208
|
-
requiredCapability?: CapabilityKey;
|
|
209
|
-
}
|
|
210
|
-
interface ProjectPageDef {
|
|
211
|
-
/** `<projectKey>.<area>`, e.g. `demoapp.datev`. */
|
|
212
|
-
id: string;
|
|
213
|
-
label: string;
|
|
214
|
-
icon?: string;
|
|
215
|
-
/** Frontend route, e.g. `/admin/datev`. */
|
|
216
|
-
route: string;
|
|
217
|
-
navSection?: string;
|
|
218
|
-
/** Lookup in the static extensions: map of the shell build. */
|
|
219
|
-
componentKey: ComponentKey;
|
|
220
|
-
requiredCapability?: CapabilityKey;
|
|
221
|
-
prefetchOnIdle?: boolean;
|
|
222
|
-
}
|
|
223
|
-
interface KpiCardDef {
|
|
224
|
-
id: string;
|
|
225
|
-
label: string;
|
|
226
|
-
/** Required path: /api/v1/admin/(extras|dashboard)/... */
|
|
227
|
-
endpoint: string;
|
|
228
|
-
displayHint: KpiDisplayHint;
|
|
229
|
-
/** 0–100; UI sorts descending. */
|
|
230
|
-
slotPriority?: number;
|
|
231
|
-
requiredCapability?: CapabilityKey;
|
|
232
|
-
}
|
|
233
|
-
interface KpiDisplayHint {
|
|
234
|
-
type: 'value' | 'value+timestamp' | 'value+spark8w' | 'value+delta';
|
|
235
|
-
icon?: string;
|
|
236
|
-
}
|
|
237
|
-
interface TenantColumnDef {
|
|
238
|
-
key: string;
|
|
239
|
-
label: string;
|
|
240
|
-
/** Required path: /api/v1/admin/extras/...; MUST be batch-capable, no {slug}/{tenantId}. */
|
|
241
|
-
endpoint: string;
|
|
242
|
-
requiredCapability?: CapabilityKey;
|
|
243
|
-
}
|
|
244
|
-
interface TenantActionDef {
|
|
245
|
-
/** `<projectKey>.<area>.<verb>`, e.g. `demoapp.datev.runExport`. */
|
|
246
|
-
id: string;
|
|
247
|
-
label: string;
|
|
248
|
-
/** Lookup in the static actions: map of the shell build. */
|
|
249
|
-
actionKey: ActionKey;
|
|
250
|
-
requiredCapability?: CapabilityKey;
|
|
251
|
-
requiresMfa?: boolean;
|
|
252
|
-
confirmType?: 'none' | 'simple' | 'typed-slug' | 'typed-production' | 'date';
|
|
253
|
-
}
|
|
254
|
-
interface AuditActionDef {
|
|
255
|
-
/** SCREAMING_SNAKE_CASE; matched to the AuditLog.action column. */
|
|
256
|
-
key: string;
|
|
257
|
-
label: string;
|
|
258
|
-
severity?: 'info' | 'low' | 'medium' | 'high';
|
|
259
|
-
}
|
|
260
|
-
interface ManifestContribution {
|
|
261
|
-
capabilities?: Record<CapabilityKey, boolean>;
|
|
262
|
-
navigation?: {
|
|
263
|
-
standardPages?: Partial<Record<StandardPageKey, StandardPageDef>>;
|
|
264
|
-
projectPages?: ProjectPageDef[];
|
|
265
|
-
};
|
|
266
|
-
dashboard?: {
|
|
267
|
-
kpiCards?: KpiCardDef[];
|
|
268
|
-
};
|
|
269
|
-
tenants?: {
|
|
270
|
-
columns?: TenantColumnDef[];
|
|
271
|
-
actions?: TenantActionDef[];
|
|
272
|
-
};
|
|
273
|
-
audit?: {
|
|
274
|
-
actions?: AuditActionDef[];
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
interface PublicBootResponse {
|
|
278
|
-
project: {
|
|
279
|
-
key: string;
|
|
280
|
-
displayName: string;
|
|
281
|
-
/** Tag/subtitle (e.g. "SuperAdmin"). From `saas.yaml#app.label`. */
|
|
282
|
-
label?: string;
|
|
283
|
-
/** Short abbreviation for the logo badge (e.g. "ma", "da"). From `saas.yaml#app.icon`. */
|
|
284
|
-
icon?: string;
|
|
285
|
-
logoUrl?: string;
|
|
286
|
-
environment?: 'production' | 'staging' | 'development';
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** Format: 'web:<email>:<sessionId>' or 'cli:<email>:<host>'. */
|
|
291
|
-
type ActorTag = string;
|
|
292
|
-
interface AuditEntry {
|
|
293
|
-
id: string;
|
|
294
|
-
/** null = platform action without tenant context (SUPER_ADMIN). */
|
|
295
|
-
tenantId: string | null;
|
|
296
|
-
/** null = system / cron-triggered. */
|
|
297
|
-
userId: string | null;
|
|
298
|
-
/** Convenience field; backend resolves it from userId. */
|
|
299
|
-
userEmail: string | null;
|
|
300
|
-
/** e.g. 'Tenant', 'PromoCode', 'Subscription', 'PlanVersion', 'User'. */
|
|
301
|
-
entity: string;
|
|
302
|
-
entityId: string;
|
|
303
|
-
/** SCREAMING_SNAKE_CASE; past-tense oriented. */
|
|
304
|
-
action: string;
|
|
305
|
-
/** Freely structured. Convention: { field: { old, new } } or { reason, ... }. */
|
|
306
|
-
changes: Record<string, unknown> | null;
|
|
307
|
-
actorTag: ActorTag | null;
|
|
308
|
-
ipAddress: string | null;
|
|
309
|
-
userAgent: string | null;
|
|
310
|
-
createdAt: string;
|
|
311
|
-
}
|
|
312
|
-
interface AuditQuery {
|
|
313
|
-
tenantId?: string;
|
|
314
|
-
userId?: string;
|
|
315
|
-
entity?: string;
|
|
316
|
-
entityId?: string;
|
|
317
|
-
action?: string;
|
|
318
|
-
/** Wildcard-capable, e.g. 'cli:*'. */
|
|
319
|
-
actorTag?: string;
|
|
320
|
-
from?: string;
|
|
321
|
-
to?: string;
|
|
322
|
-
page?: number;
|
|
323
|
-
pageSize?: number;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
88
|
/**
|
|
327
89
|
* Approval lifecycle of a feature or a quota. Approval happens per
|
|
328
90
|
* FEATURE/QUOTA — not per capability (#20); only `approved` entries
|
|
@@ -385,7 +147,6 @@ type CatalogEntryI18n = Record<string, CatalogEntryI18nFields>;
|
|
|
385
147
|
*/
|
|
386
148
|
interface CapabilityCatalogEntryRow {
|
|
387
149
|
id: string;
|
|
388
|
-
projectKey: string;
|
|
389
150
|
capabilityKey: string;
|
|
390
151
|
label: string;
|
|
391
152
|
description: string | null;
|
|
@@ -422,7 +183,6 @@ type FeatureTier = 'CORE' | 'ADVANCED' | 'PRO' | 'ENTERPRISE' | string;
|
|
|
422
183
|
*/
|
|
423
184
|
interface FeatureCatalogEntryRow {
|
|
424
185
|
id: string;
|
|
425
|
-
projectKey: string;
|
|
426
186
|
featureKey: string;
|
|
427
187
|
label: string;
|
|
428
188
|
description: string | null;
|
|
@@ -477,7 +237,6 @@ interface FeatureCatalogEntryRow {
|
|
|
477
237
|
*/
|
|
478
238
|
interface QuotaCatalogEntryRow {
|
|
479
239
|
id: string;
|
|
480
|
-
projectKey: string;
|
|
481
240
|
quotaKey: string;
|
|
482
241
|
label: string;
|
|
483
242
|
description: string | null;
|
|
@@ -521,7 +280,6 @@ interface QuotaCatalogEntryRow {
|
|
|
521
280
|
* matching field is relevant.
|
|
522
281
|
*/
|
|
523
282
|
interface CatalogEntryFilter {
|
|
524
|
-
projectKey: string;
|
|
525
283
|
discoveryStatus?: DiscoveryStatus;
|
|
526
284
|
codeStatus?: CapabilityCodeStatus;
|
|
527
285
|
}
|
|
@@ -635,7 +393,6 @@ declare const MARKETING_PRIORITY_MAX = 10000;
|
|
|
635
393
|
*/
|
|
636
394
|
interface MarketingProjectionRow {
|
|
637
395
|
id: string;
|
|
638
|
-
projectKey: string;
|
|
639
396
|
targetType: MarketingTargetType;
|
|
640
397
|
targetVersionId: string;
|
|
641
398
|
/** ISO-639-1, optionally with region suffix (`de`, `en`, `de-AT`). */
|
|
@@ -680,15 +437,13 @@ interface MarketingProjectionRow {
|
|
|
680
437
|
createdAt: string;
|
|
681
438
|
updatedAt: string;
|
|
682
439
|
}
|
|
683
|
-
/** Filter for `MarketingProjectionRepository.list()`.
|
|
440
|
+
/** Filter for `MarketingProjectionRepository.list()`. */
|
|
684
441
|
interface MarketingProjectionFilter {
|
|
685
|
-
projectKey: string;
|
|
686
442
|
targetType?: MarketingTargetType;
|
|
687
443
|
targetVersionId?: string;
|
|
688
444
|
locale?: string;
|
|
689
445
|
}
|
|
690
446
|
interface CreateMarketingProjectionData {
|
|
691
|
-
projectKey: string;
|
|
692
447
|
targetType: MarketingTargetType;
|
|
693
448
|
targetVersionId: string;
|
|
694
449
|
locale?: string;
|
|
@@ -718,14 +473,87 @@ interface UpdateMarketingProjectionData {
|
|
|
718
473
|
highlight?: boolean;
|
|
719
474
|
}
|
|
720
475
|
|
|
721
|
-
type
|
|
722
|
-
type
|
|
723
|
-
type
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
/**
|
|
476
|
+
type FeatureKey = string;
|
|
477
|
+
type PlanId = string;
|
|
478
|
+
type QuotaKey = string;
|
|
479
|
+
interface FeatureDef {
|
|
480
|
+
key: FeatureKey;
|
|
481
|
+
label?: string;
|
|
482
|
+
icon?: string;
|
|
483
|
+
/** CORE / ADVANCED / PRO / BUSINESS / ENTERPRISE_ONLY — convention. */
|
|
484
|
+
tier?: string;
|
|
485
|
+
plannedOnly?: boolean;
|
|
486
|
+
}
|
|
487
|
+
interface PlanDef {
|
|
488
|
+
id: PlanId;
|
|
489
|
+
name?: string;
|
|
490
|
+
tagline?: string;
|
|
491
|
+
/** false = not selectable in self-service onboarding. Default: true. */
|
|
492
|
+
marketed?: boolean;
|
|
493
|
+
/** Highlighted card in onboarding (max. 1 per catalog). */
|
|
494
|
+
popular?: boolean;
|
|
495
|
+
/** Net monthly price. null = on request. */
|
|
496
|
+
monthlyNet?: number | null;
|
|
497
|
+
/** Net total amount per year. null = monthly only. */
|
|
498
|
+
yearlyNet?: number | null;
|
|
499
|
+
/** Map quotaKey → max value. -1 = unlimited. */
|
|
500
|
+
quotas: Record<QuotaKey, number>;
|
|
501
|
+
features: FeatureKey[];
|
|
502
|
+
}
|
|
503
|
+
/** App-wide marketing configuration. */
|
|
504
|
+
interface PlanCatalogMarketing {
|
|
505
|
+
/**
|
|
506
|
+
* Allowed language pool that the app may market. First = default
|
|
507
|
+
* locale. From it, the SuperAdmin activates a subset in the marketing
|
|
508
|
+
* catalog (LocaleManager).
|
|
509
|
+
*/
|
|
510
|
+
availableLocales: string[];
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* App identity block for branding + version. Consumed by the `AdminPublicBootController`
|
|
514
|
+
* and the `AdminManifestConfigFactory`; the SuperAdmin UI (platform
|
|
515
|
+
* LoginPage, AdminLayout brand block) reads the same fields via PublicBoot.
|
|
516
|
+
*
|
|
517
|
+
* `name` = brand display name (e.g. "DemoApp", "ClubApp").
|
|
518
|
+
* `label` = tag/subtitle in the brand block (e.g. "SuperAdmin").
|
|
519
|
+
* `version` = app version string (build info).
|
|
520
|
+
* `icon` = 2-character abbreviation for the logo badge (e.g. "ma", "da").
|
|
521
|
+
* `logoUrl` = optional URL to a PNG/SVG; if set, the UI renders an <img>
|
|
522
|
+
* instead of the initials badge.
|
|
523
|
+
*/
|
|
524
|
+
interface PlanCatalogApp {
|
|
525
|
+
name: string;
|
|
526
|
+
label?: string;
|
|
527
|
+
version?: string;
|
|
528
|
+
icon?: string;
|
|
529
|
+
logoUrl?: string;
|
|
530
|
+
}
|
|
531
|
+
interface PlanCatalog {
|
|
532
|
+
schemaVersion: 1;
|
|
533
|
+
/** App identity (branding + version), see PlanCatalogApp. */
|
|
534
|
+
app: PlanCatalogApp;
|
|
535
|
+
/** ISO-4217 currency code. */
|
|
536
|
+
currency: string;
|
|
537
|
+
/** VAT rate in percent. */
|
|
538
|
+
vatRate: number;
|
|
539
|
+
/** App-wide marketing configuration. Optional. */
|
|
540
|
+
marketing?: PlanCatalogMarketing;
|
|
541
|
+
features?: FeatureDef[];
|
|
542
|
+
/**
|
|
543
|
+
* Optional. When omitted, plans come exclusively from the
|
|
544
|
+
* AdminUI / DB table (Plans/PlanVersions lifecycle).
|
|
545
|
+
*/
|
|
546
|
+
plans?: PlanDef[];
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
type PromoCodeValueType = 'PERCENT' | 'ABSOLUTE';
|
|
550
|
+
type PromoCodeDurationType = 'ONCE' | 'MONTHS' | 'BILLING_CYCLES';
|
|
551
|
+
type PromoCodeStatus = 'ACTIVE' | 'PAUSED' | 'EXHAUSTED' | 'EXPIRED';
|
|
552
|
+
type PromoCodeRedemptionStatus = 'ACTIVE' | 'REVERSED' | 'EXPIRED';
|
|
553
|
+
type BillingCycle = 'MONTHLY' | 'YEARLY';
|
|
554
|
+
type PromoCodeValidationResult = 'VALID' | 'EXPIRED' | 'EXHAUSTED' | 'NOT_FOUND' | 'PAUSED' | 'NOT_APPLICABLE' | 'FIRST_TIME_ONLY' | 'ZERO_INVOICE_BLOCKED' | 'MIN_AMOUNT_NOT_REACHED' | 'RATE_LIMITED';
|
|
555
|
+
interface CreatePromoCodeRequest {
|
|
556
|
+
/** A–Z, 0–9, '-' and '_'; 4–32 characters; case-insensitive, stored in UPPER. */
|
|
729
557
|
code: string;
|
|
730
558
|
valueType: PromoCodeValueType;
|
|
731
559
|
/** For PERCENT: 0.01–100. For ABSOLUTE: > 0 in catalog currency. */
|
|
@@ -914,7 +742,7 @@ interface VersionedEntityBase {
|
|
|
914
742
|
* own migration).
|
|
915
743
|
* - `startedAt` is the contract start of this booking.
|
|
916
744
|
* - `minimumTermEndsAt` = end of the minimum term; `null` = no minimum term
|
|
917
|
-
* (platform default =
|
|
745
|
+
* (platform default = no commitment, set service-side).
|
|
918
746
|
* - `canceledAt` / `canceledEffectiveAt`: cancellation anchor vs. effective
|
|
919
747
|
* date. Before the minimum term ends, `canceledEffectiveAt =
|
|
920
748
|
* minimumTermEndsAt`, otherwise the subscription's period end.
|
|
@@ -931,6 +759,18 @@ interface SubscriptionBundleRecord {
|
|
|
931
759
|
minimumTermEndsAt: Date | null;
|
|
932
760
|
canceledAt: Date | null;
|
|
933
761
|
canceledEffectiveAt: Date | null;
|
|
762
|
+
/**
|
|
763
|
+
* The rhythm this booking is billed in, and the window it is billed for.
|
|
764
|
+
*
|
|
765
|
+
* A bundle's periods end on the day its plan's do — the first one short,
|
|
766
|
+
* from the booking to the next occurrence of that day, and every one after
|
|
767
|
+
* it anchor to anchor. Null on a booking made before these fields existed,
|
|
768
|
+
* or on one whose plan has no period; readers fall back to the plan's
|
|
769
|
+
* cycle, which is what every booking used before.
|
|
770
|
+
*/
|
|
771
|
+
billingCycle: string | null;
|
|
772
|
+
currentPeriodStart: Date | null;
|
|
773
|
+
currentPeriodEnd: Date | null;
|
|
934
774
|
createdAt: Date;
|
|
935
775
|
updatedAt: Date;
|
|
936
776
|
}
|
|
@@ -944,14 +784,27 @@ interface SubscriptionBundleRecord {
|
|
|
944
784
|
interface SubscriptionBundleView extends SubscriptionBundleRecord {
|
|
945
785
|
bundleKey: string | null;
|
|
946
786
|
label: string | null;
|
|
947
|
-
|
|
787
|
+
/**
|
|
788
|
+
* What this booking is billed at, in the rhythm it was booked in and with
|
|
789
|
+
* the plan's pricing override applied.
|
|
790
|
+
*
|
|
791
|
+
* It was `monthlyNet` until 2026-08-27 and carried the bundle's base
|
|
792
|
+
* monthly price whatever the booking was — so a yearly booking of a bundle
|
|
793
|
+
* priced 10 monthly and 100 yearly reported 10. The name was half the
|
|
794
|
+
* defect: a field called `monthlyNet` on a yearly booking cannot be right.
|
|
795
|
+
*/
|
|
796
|
+
priceNet: number | null;
|
|
948
797
|
}
|
|
949
798
|
interface CreateSubscriptionBundleData {
|
|
950
799
|
subscriptionId: string;
|
|
951
800
|
bundleVersionId: string;
|
|
952
801
|
startedAt: Date;
|
|
953
|
-
/**
|
|
802
|
+
/** Null unless a commitment was configured or asked for. */
|
|
954
803
|
minimumTermEndsAt?: Date | null;
|
|
804
|
+
/** The rhythm and window worked out above this port. */
|
|
805
|
+
billingCycle?: string | null;
|
|
806
|
+
currentPeriodStart?: Date | null;
|
|
807
|
+
currentPeriodEnd?: Date | null;
|
|
955
808
|
}
|
|
956
809
|
interface CancelSubscriptionBundleData {
|
|
957
810
|
canceledAt: Date;
|
|
@@ -1000,7 +853,6 @@ interface BundlePricingOverride {
|
|
|
1000
853
|
*/
|
|
1001
854
|
interface BundleRow {
|
|
1002
855
|
id: string;
|
|
1003
|
-
projectKey: string;
|
|
1004
856
|
bundleKey: string;
|
|
1005
857
|
label: string;
|
|
1006
858
|
description: string | null;
|
|
@@ -1039,7 +891,6 @@ interface BundleVersionRow extends VersionedEntityBase {
|
|
|
1039
891
|
* first BundleVersion via `CreateBundleVersionDraftData`.
|
|
1040
892
|
*/
|
|
1041
893
|
interface CreateBundleData {
|
|
1042
|
-
projectKey: string;
|
|
1043
894
|
bundleKey: string;
|
|
1044
895
|
label: string;
|
|
1045
896
|
description?: string | null;
|
|
@@ -1048,9 +899,9 @@ interface CreateBundleData {
|
|
|
1048
899
|
i18n?: CatalogEntryI18n;
|
|
1049
900
|
}
|
|
1050
901
|
/**
|
|
1051
|
-
* Fields that may be changed on the bundle master. `bundleKey`
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
902
|
+
* Fields that may be changed on the bundle master. `bundleKey` is
|
|
903
|
+
* intentionally not here — master identity is immutable; whoever wants to
|
|
904
|
+
* change it creates a new bundle and retires the old one.
|
|
1054
905
|
*/
|
|
1055
906
|
interface UpdateBundleData {
|
|
1056
907
|
label?: string;
|
|
@@ -1116,73 +967,330 @@ interface UpdateBundleVersionDraftData {
|
|
|
1116
967
|
validFrom?: string | null;
|
|
1117
968
|
validUntil?: string | null;
|
|
1118
969
|
}
|
|
1119
|
-
/**
|
|
1120
|
-
* Input for `publishBundleVersion()`. `nonRegressive` and
|
|
1121
|
-
* `publishedChanges` are computed by the service from the diff against the
|
|
1122
|
-
* predecessor version; the caller supplies only confirmation
|
|
1123
|
-
* + user tag + validity dates.
|
|
1124
|
-
*
|
|
1125
|
-
* `validFrom` is **required** at publish (analogous to `PublishPlanVersionData`).
|
|
1126
|
-
* If the draft already carries a `validFrom`, it is optional here. The
|
|
1127
|
-
* service validates strictly > `validFrom` of the predecessor version and sets
|
|
1128
|
-
* its `validUntil` via auto succession to `validFrom - 1 day`.
|
|
1129
|
-
*/
|
|
1130
|
-
interface PublishBundleVersionData {
|
|
1131
|
-
publishedByUserId: string | null;
|
|
1132
|
-
/**
|
|
1133
|
-
* If true and the diff classifies the version as regressive,
|
|
1134
|
-
* it is published anyway — relevant for bulk-publish MFA confirmation
|
|
1135
|
-
* ( editor-UI obligations).
|
|
1136
|
-
*/
|
|
1137
|
-
forceRegressive?: boolean;
|
|
1138
|
-
/**
|
|
1139
|
-
* Allows publish despite an explicit price of 0.00. Default false: an
|
|
1140
|
-
* explicit 0.00 publish is blocked (protection against seed placeholders).
|
|
1141
|
-
* `null` prices (override resolution) are not affected.
|
|
1142
|
-
*/
|
|
1143
|
-
allowZeroPrice?: boolean;
|
|
1144
|
-
/**
|
|
1145
|
-
* Required at publish if the draft has no `validFrom`. Must lie
|
|
1146
|
-
* strictly after `validFrom` of the predecessor version. ISO-8601
|
|
1147
|
-
* (`YYYY-MM-DD` or full timestamp).
|
|
1148
|
-
*/
|
|
1149
|
-
validFrom?: string | null;
|
|
1150
|
-
/**
|
|
1151
|
-
* Optional; null = valid indefinitely (fits the last version
|
|
1152
|
-
* of a bundle). When a successor version is created it is automatically
|
|
1153
|
-
* overwritten by the service.
|
|
1154
|
-
*/
|
|
1155
|
-
validUntil?: string | null;
|
|
970
|
+
/**
|
|
971
|
+
* Input for `publishBundleVersion()`. `nonRegressive` and
|
|
972
|
+
* `publishedChanges` are computed by the service from the diff against the
|
|
973
|
+
* predecessor version; the caller supplies only confirmation
|
|
974
|
+
* + user tag + validity dates.
|
|
975
|
+
*
|
|
976
|
+
* `validFrom` is **required** at publish (analogous to `PublishPlanVersionData`).
|
|
977
|
+
* If the draft already carries a `validFrom`, it is optional here. The
|
|
978
|
+
* service validates strictly > `validFrom` of the predecessor version and sets
|
|
979
|
+
* its `validUntil` via auto succession to `validFrom - 1 day`.
|
|
980
|
+
*/
|
|
981
|
+
interface PublishBundleVersionData {
|
|
982
|
+
publishedByUserId: string | null;
|
|
983
|
+
/**
|
|
984
|
+
* If true and the diff classifies the version as regressive,
|
|
985
|
+
* it is published anyway — relevant for bulk-publish MFA confirmation
|
|
986
|
+
* ( editor-UI obligations).
|
|
987
|
+
*/
|
|
988
|
+
forceRegressive?: boolean;
|
|
989
|
+
/**
|
|
990
|
+
* Allows publish despite an explicit price of 0.00. Default false: an
|
|
991
|
+
* explicit 0.00 publish is blocked (protection against seed placeholders).
|
|
992
|
+
* `null` prices (override resolution) are not affected.
|
|
993
|
+
*/
|
|
994
|
+
allowZeroPrice?: boolean;
|
|
995
|
+
/**
|
|
996
|
+
* Required at publish if the draft has no `validFrom`. Must lie
|
|
997
|
+
* strictly after `validFrom` of the predecessor version. ISO-8601
|
|
998
|
+
* (`YYYY-MM-DD` or full timestamp).
|
|
999
|
+
*/
|
|
1000
|
+
validFrom?: string | null;
|
|
1001
|
+
/**
|
|
1002
|
+
* Optional; null = valid indefinitely (fits the last version
|
|
1003
|
+
* of a bundle). When a successor version is created it is automatically
|
|
1004
|
+
* overwritten by the service.
|
|
1005
|
+
*/
|
|
1006
|
+
validUntil?: string | null;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Code of a strict-mode violation. lists the eight rules
|
|
1010
|
+
* that are checked; each rule has its own code so the UI can show
|
|
1011
|
+
* focused help texts.
|
|
1012
|
+
*/
|
|
1013
|
+
type StrictModeWarningCode = 'CAPABILITY_MISSING' | 'CAPABILITY_RETIRED' | 'FEATURE_MISSING' | 'FEATURE_PLANNED_ONLY' | 'BUNDLE_FEATURE_UNKNOWN' | 'BUNDLE_PLAN_KEY_UNKNOWN' | 'PLAN_FEATURE_UNKNOWN' | 'PLAN_FEATURE_NOT_APPROVED' | 'BUNDLE_FEATURE_NOT_APPROVED' | 'PLAN_FEATURE_DEPENDENCY_UNSATISFIED' | 'BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED' | 'QUOTA_MISSING' | 'QUOTA_NOT_APPROVED' | 'VERSION_PUBLISH_OVERLAP';
|
|
1014
|
+
/**
|
|
1015
|
+
* A strict-mode violation. `field` points to the violating field
|
|
1016
|
+
* (e.g. `'features[3]'`), `value` is the concrete value (e.g. `'INVENTORY'`).
|
|
1017
|
+
*/
|
|
1018
|
+
interface StrictModeWarning {
|
|
1019
|
+
code: StrictModeWarningCode;
|
|
1020
|
+
/** Human-readable reason (German). */
|
|
1021
|
+
message: string;
|
|
1022
|
+
/** Path to the violating field; optional. */
|
|
1023
|
+
field?: string;
|
|
1024
|
+
/** The concrete violating value; optional. */
|
|
1025
|
+
value?: string;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Service result for mutating Bundle operations
|
|
1029
|
+
* (createDraft, updateDraft, publish): returns the persisted row plus
|
|
1030
|
+
* a list of strict-mode warnings. In `warn-only` mode the
|
|
1031
|
+
* warnings go into the UI as a banner; in `blocking` mode the service throws
|
|
1032
|
+
* HTTP 422 instead, with the same warning list as the body.
|
|
1033
|
+
*/
|
|
1034
|
+
interface BundleVersionMutationResult {
|
|
1035
|
+
bundleVersion: BundleVersionRow;
|
|
1036
|
+
warnings: StrictModeWarning[];
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* The column values a new BundleVersion draft starts from.
|
|
1041
|
+
*
|
|
1042
|
+
* Every adapter has to apply the same defaults — an absent quota map is `{}`,
|
|
1043
|
+
* an absent price is null rather than zero, an unstated `marketed` is true —
|
|
1044
|
+
* and two adapters spelling that out separately is the same decision written
|
|
1045
|
+
* twice. It is also the variant jscpd does catch, which is how this came out:
|
|
1046
|
+
* `adapter-drizzle` learning about bundles put a second copy beside
|
|
1047
|
+
* `adapter-prisma`'s.
|
|
1048
|
+
*
|
|
1049
|
+
* Validity windows are deliberately absent. Whether a draft carries
|
|
1050
|
+
* `validFrom`/`validUntil` is an adapter capability rather than a default, and
|
|
1051
|
+
* an adapter that does not maintain those columns must not write them.
|
|
1052
|
+
*/
|
|
1053
|
+
declare function bundleDraftDefaults(data: CreateBundleVersionDraftData): {
|
|
1054
|
+
baseVersionId: string | null;
|
|
1055
|
+
features: string[];
|
|
1056
|
+
quotas: Record<string, number>;
|
|
1057
|
+
compatibility: Record<string, unknown>;
|
|
1058
|
+
pricingOverrides: unknown[];
|
|
1059
|
+
monthlyNet: string | null;
|
|
1060
|
+
yearlyNet: string | null;
|
|
1061
|
+
marketed: boolean;
|
|
1062
|
+
changeNote: string;
|
|
1063
|
+
createdByUserId: string | null;
|
|
1064
|
+
};
|
|
1065
|
+
/**
|
|
1066
|
+
* The column values a new Bundle stem starts from.
|
|
1067
|
+
*
|
|
1068
|
+
* The same defaulting rule as above, one level up: an absent description or
|
|
1069
|
+
* icon is null rather than an empty string, an unstated sort order is 0, an
|
|
1070
|
+
* absent translation map is `{}`. Written out in five places before this — two
|
|
1071
|
+
* adapters and two fakes — which is four opportunities for one of them to
|
|
1072
|
+
* decide differently.
|
|
1073
|
+
*/
|
|
1074
|
+
declare function bundleStemDefaults(data: CreateBundleData): {
|
|
1075
|
+
bundleKey: string;
|
|
1076
|
+
label: string;
|
|
1077
|
+
description: string | null;
|
|
1078
|
+
icon: string | null;
|
|
1079
|
+
sortOrder: number;
|
|
1080
|
+
i18n: CatalogEntryI18n;
|
|
1081
|
+
};
|
|
1082
|
+
/** The stored shape both adapters read a bundle stem back from. */
|
|
1083
|
+
interface StoredBundleStem {
|
|
1084
|
+
id: string;
|
|
1085
|
+
bundleKey: string;
|
|
1086
|
+
label: string;
|
|
1087
|
+
description: string | null;
|
|
1088
|
+
icon: string | null;
|
|
1089
|
+
sortOrder: number;
|
|
1090
|
+
i18n: unknown;
|
|
1091
|
+
createdAt: Date;
|
|
1092
|
+
updatedAt: Date;
|
|
1093
|
+
deletedAt: Date | null;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* A stored bundle stem as the port describes it.
|
|
1097
|
+
*
|
|
1098
|
+
* The two stores spell the columns identically, so the mapping was identical
|
|
1099
|
+
* too — and an identical mapping in two files is one place for a field to be
|
|
1100
|
+
* forgotten when the row grows. `i18n` arrives as JSON of unknown shape from
|
|
1101
|
+
* both, and a non-object becomes `{}` rather than reaching a caller that
|
|
1102
|
+
* expects a map.
|
|
1103
|
+
*/
|
|
1104
|
+
declare function toBundleStemRow(row: StoredBundleStem): BundleRow;
|
|
1105
|
+
/**
|
|
1106
|
+
* The fields a caller actually gave, as a patch.
|
|
1107
|
+
*
|
|
1108
|
+
* The update DTOs in this codebase mean three different things by three
|
|
1109
|
+
* different values: a value changes the column, an explicit `null` clears it,
|
|
1110
|
+
* and an **omitted** field leaves it alone. Only the last one needs care, and
|
|
1111
|
+
* it was written out as `...(data.x !== undefined ? { x: data.x } : {})` more
|
|
1112
|
+
* than fifty times across five repositories — one decision, fifty
|
|
1113
|
+
* opportunities to spell it differently, and the duplication ratchet is what
|
|
1114
|
+
* finally pointed at it.
|
|
1115
|
+
*
|
|
1116
|
+
* `null` is deliberately kept: it is a value a caller chose, not an absence.
|
|
1117
|
+
*/
|
|
1118
|
+
declare function definedFields<T extends object, K extends keyof T>(data: T, keys: readonly K[]): Partial<Pick<T, K>>;
|
|
1119
|
+
|
|
1120
|
+
/** Backend capability key, convention: domain.action[.action]. */
|
|
1121
|
+
type CapabilityKey = string;
|
|
1122
|
+
/** Frontend action-registry key. Same convention as CapabilityKey. */
|
|
1123
|
+
type ActionKey = CapabilityKey;
|
|
1124
|
+
/** Lookup key in the static extensions: map of the UI build. */
|
|
1125
|
+
type ComponentKey = string;
|
|
1126
|
+
interface AdminManifest {
|
|
1127
|
+
schemaVersion: 1;
|
|
1128
|
+
project: {
|
|
1129
|
+
key: string;
|
|
1130
|
+
displayName: string;
|
|
1131
|
+
/** Tag/subtitle (e.g. "SuperAdmin"). From `saas.yaml#app.label`. */
|
|
1132
|
+
label?: string;
|
|
1133
|
+
/** Short abbreviation for the logo badge (e.g. "ma", "da"). From `saas.yaml#app.icon`. */
|
|
1134
|
+
icon?: string;
|
|
1135
|
+
logoUrl?: string;
|
|
1136
|
+
environment?: 'production' | 'staging' | 'development';
|
|
1137
|
+
/**
|
|
1138
|
+
* Allowed locale pool from the app config (`saas.yaml`
|
|
1139
|
+
* `marketing.availableLocales`). First = default..
|
|
1140
|
+
*/
|
|
1141
|
+
availableLocales?: string[];
|
|
1142
|
+
/** Default locale; equals `availableLocales[0]`. */
|
|
1143
|
+
defaultLocale?: string;
|
|
1144
|
+
};
|
|
1145
|
+
build: {
|
|
1146
|
+
platformPackageVersion: string;
|
|
1147
|
+
appVersion: string;
|
|
1148
|
+
manifestHash: string;
|
|
1149
|
+
};
|
|
1150
|
+
planCatalogSnapshot: {
|
|
1151
|
+
source: string;
|
|
1152
|
+
hash: string;
|
|
1153
|
+
currency: string;
|
|
1154
|
+
vatRate: number;
|
|
1155
|
+
features?: FeatureDef[];
|
|
1156
|
+
plans: PlanDef[];
|
|
1157
|
+
};
|
|
1158
|
+
/** Map CapabilityKey → boolean. Manifest is never a security source. */
|
|
1159
|
+
capabilities: Record<CapabilityKey, boolean>;
|
|
1160
|
+
navigation: {
|
|
1161
|
+
standardPages: Partial<Record<StandardPageKey, StandardPageDef>>;
|
|
1162
|
+
projectPages?: ProjectPageDef[];
|
|
1163
|
+
};
|
|
1164
|
+
dashboard?: {
|
|
1165
|
+
kpiCards?: KpiCardDef[];
|
|
1166
|
+
};
|
|
1167
|
+
tenants?: {
|
|
1168
|
+
columns?: TenantColumnDef[];
|
|
1169
|
+
actions?: TenantActionDef[];
|
|
1170
|
+
};
|
|
1171
|
+
audit?: {
|
|
1172
|
+
actions?: AuditActionDef[];
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
type StandardPageKey = 'dashboard' | 'tenants' | 'subscriptions' | 'promoCodes' | 'plans' | 'audit' | 'users' | 'pilots' | 'discovery' | 'bundles' | 'marketingCatalog' | 'platformEmail' | 'platformEmailHistory';
|
|
1176
|
+
interface StandardPageDef {
|
|
1177
|
+
enabled: boolean;
|
|
1178
|
+
requiredCapability?: CapabilityKey;
|
|
1179
|
+
}
|
|
1180
|
+
interface ProjectPageDef {
|
|
1181
|
+
/** `<app>.<area>`, e.g. `demoapp.datev`. */
|
|
1182
|
+
id: string;
|
|
1183
|
+
label: string;
|
|
1184
|
+
icon?: string;
|
|
1185
|
+
/** Frontend route, e.g. `/admin/datev`. */
|
|
1186
|
+
route: string;
|
|
1187
|
+
navSection?: string;
|
|
1188
|
+
/** Lookup in the static extensions: map of the shell build. */
|
|
1189
|
+
componentKey: ComponentKey;
|
|
1190
|
+
requiredCapability?: CapabilityKey;
|
|
1191
|
+
prefetchOnIdle?: boolean;
|
|
1192
|
+
}
|
|
1193
|
+
interface KpiCardDef {
|
|
1194
|
+
id: string;
|
|
1195
|
+
label: string;
|
|
1196
|
+
/** Required path: /api/v1/admin/(extras|dashboard)/... */
|
|
1197
|
+
endpoint: string;
|
|
1198
|
+
displayHint: KpiDisplayHint;
|
|
1199
|
+
/** 0–100; UI sorts descending. */
|
|
1200
|
+
slotPriority?: number;
|
|
1201
|
+
requiredCapability?: CapabilityKey;
|
|
1202
|
+
}
|
|
1203
|
+
interface KpiDisplayHint {
|
|
1204
|
+
type: 'value' | 'value+timestamp' | 'value+spark8w' | 'value+delta';
|
|
1205
|
+
icon?: string;
|
|
1206
|
+
}
|
|
1207
|
+
interface TenantColumnDef {
|
|
1208
|
+
key: string;
|
|
1209
|
+
label: string;
|
|
1210
|
+
/** Required path: /api/v1/admin/extras/...; MUST be batch-capable, no {slug}/{tenantId}. */
|
|
1211
|
+
endpoint: string;
|
|
1212
|
+
requiredCapability?: CapabilityKey;
|
|
1213
|
+
}
|
|
1214
|
+
interface TenantActionDef {
|
|
1215
|
+
/** `<app>.<area>.<verb>`, e.g. `demoapp.datev.runExport`. */
|
|
1216
|
+
id: string;
|
|
1217
|
+
label: string;
|
|
1218
|
+
/** Lookup in the static actions: map of the shell build. */
|
|
1219
|
+
actionKey: ActionKey;
|
|
1220
|
+
requiredCapability?: CapabilityKey;
|
|
1221
|
+
requiresMfa?: boolean;
|
|
1222
|
+
confirmType?: 'none' | 'simple' | 'typed-slug' | 'typed-production' | 'date';
|
|
1156
1223
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
type StrictModeWarningCode = 'CAPABILITY_MISSING' | 'CAPABILITY_RETIRED' | 'FEATURE_MISSING' | 'FEATURE_PLANNED_ONLY' | 'BUNDLE_FEATURE_UNKNOWN' | 'BUNDLE_PLAN_KEY_UNKNOWN' | 'PLAN_FEATURE_UNKNOWN' | 'PLAN_FEATURE_NOT_APPROVED' | 'BUNDLE_FEATURE_NOT_APPROVED' | 'PLAN_FEATURE_DEPENDENCY_UNSATISFIED' | 'BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED' | 'QUOTA_MISSING' | 'QUOTA_NOT_APPROVED' | 'VERSION_PUBLISH_OVERLAP';
|
|
1163
|
-
/**
|
|
1164
|
-
* A strict-mode violation. `field` points to the violating field
|
|
1165
|
-
* (e.g. `'features[3]'`), `value` is the concrete value (e.g. `'INVENTORY'`).
|
|
1166
|
-
*/
|
|
1167
|
-
interface StrictModeWarning {
|
|
1168
|
-
code: StrictModeWarningCode;
|
|
1169
|
-
/** Human-readable reason (German). */
|
|
1170
|
-
message: string;
|
|
1171
|
-
/** Path to the violating field; optional. */
|
|
1172
|
-
field?: string;
|
|
1173
|
-
/** The concrete violating value; optional. */
|
|
1174
|
-
value?: string;
|
|
1224
|
+
interface AuditActionDef {
|
|
1225
|
+
/** SCREAMING_SNAKE_CASE; matched to the AuditLog.action column. */
|
|
1226
|
+
key: string;
|
|
1227
|
+
label: string;
|
|
1228
|
+
severity?: 'info' | 'low' | 'medium' | 'high';
|
|
1175
1229
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1230
|
+
interface ManifestContribution {
|
|
1231
|
+
capabilities?: Record<CapabilityKey, boolean>;
|
|
1232
|
+
navigation?: {
|
|
1233
|
+
standardPages?: Partial<Record<StandardPageKey, StandardPageDef>>;
|
|
1234
|
+
projectPages?: ProjectPageDef[];
|
|
1235
|
+
};
|
|
1236
|
+
dashboard?: {
|
|
1237
|
+
kpiCards?: KpiCardDef[];
|
|
1238
|
+
};
|
|
1239
|
+
tenants?: {
|
|
1240
|
+
columns?: TenantColumnDef[];
|
|
1241
|
+
actions?: TenantActionDef[];
|
|
1242
|
+
};
|
|
1243
|
+
audit?: {
|
|
1244
|
+
actions?: AuditActionDef[];
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
interface PublicBootResponse {
|
|
1248
|
+
project: {
|
|
1249
|
+
key: string;
|
|
1250
|
+
displayName: string;
|
|
1251
|
+
/** Tag/subtitle (e.g. "SuperAdmin"). From `saas.yaml#app.label`. */
|
|
1252
|
+
label?: string;
|
|
1253
|
+
/** Short abbreviation for the logo badge (e.g. "ma", "da"). From `saas.yaml#app.icon`. */
|
|
1254
|
+
icon?: string;
|
|
1255
|
+
logoUrl?: string;
|
|
1256
|
+
environment?: 'production' | 'staging' | 'development';
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/** Format: 'web:<email>:<sessionId>' or 'cli:<email>:<host>'. */
|
|
1261
|
+
type ActorTag = string;
|
|
1262
|
+
interface AuditEntry {
|
|
1263
|
+
id: string;
|
|
1264
|
+
/** null = platform action without tenant context (SUPER_ADMIN). */
|
|
1265
|
+
tenantId: string | null;
|
|
1266
|
+
/** null = system / cron-triggered. */
|
|
1267
|
+
userId: string | null;
|
|
1268
|
+
/** Convenience field; backend resolves it from userId. */
|
|
1269
|
+
userEmail: string | null;
|
|
1270
|
+
/** e.g. 'Tenant', 'PromoCode', 'Subscription', 'PlanVersion', 'User'. */
|
|
1271
|
+
entity: string;
|
|
1272
|
+
entityId: string;
|
|
1273
|
+
/** SCREAMING_SNAKE_CASE; past-tense oriented. */
|
|
1274
|
+
action: string;
|
|
1275
|
+
/** Freely structured. Convention: { field: { old, new } } or { reason, ... }. */
|
|
1276
|
+
changes: Record<string, unknown> | null;
|
|
1277
|
+
actorTag: ActorTag | null;
|
|
1278
|
+
ipAddress: string | null;
|
|
1279
|
+
userAgent: string | null;
|
|
1280
|
+
createdAt: string;
|
|
1281
|
+
}
|
|
1282
|
+
interface AuditQuery {
|
|
1283
|
+
tenantId?: string;
|
|
1284
|
+
userId?: string;
|
|
1285
|
+
entity?: string;
|
|
1286
|
+
entityId?: string;
|
|
1287
|
+
action?: string;
|
|
1288
|
+
/** Wildcard-capable, e.g. 'cli:*'. */
|
|
1289
|
+
actorTag?: string;
|
|
1290
|
+
from?: string;
|
|
1291
|
+
to?: string;
|
|
1292
|
+
page?: number;
|
|
1293
|
+
pageSize?: number;
|
|
1186
1294
|
}
|
|
1187
1295
|
|
|
1188
1296
|
/** Promotion type. */
|
|
@@ -1213,7 +1321,6 @@ type PromotionI18n = Record<string, PromotionI18nFields>;
|
|
|
1213
1321
|
/** Wire format of a `promotions` row. */
|
|
1214
1322
|
interface PromotionRow {
|
|
1215
1323
|
id: string;
|
|
1216
|
-
projectKey: string;
|
|
1217
1324
|
/** Internal label (not public). */
|
|
1218
1325
|
internalLabel: string;
|
|
1219
1326
|
type: PromotionType;
|
|
@@ -1239,11 +1346,7 @@ interface PromotionRow {
|
|
|
1239
1346
|
createdAt: string;
|
|
1240
1347
|
updatedAt: string;
|
|
1241
1348
|
}
|
|
1242
|
-
interface PromotionFilter {
|
|
1243
|
-
projectKey: string;
|
|
1244
|
-
}
|
|
1245
1349
|
interface CreatePromotionData {
|
|
1246
|
-
projectKey: string;
|
|
1247
1350
|
internalLabel: string;
|
|
1248
1351
|
type: PromotionType;
|
|
1249
1352
|
value: PromotionValue;
|
|
@@ -1366,7 +1469,6 @@ type CheckoutOfferStatus = 'open' | 'consumed' | 'expired';
|
|
|
1366
1469
|
/** Wire format of a `checkout_offers` row. */
|
|
1367
1470
|
interface CheckoutOfferRow {
|
|
1368
1471
|
id: string;
|
|
1369
|
-
projectKey: string;
|
|
1370
1472
|
/** Plan selected on the website. */
|
|
1371
1473
|
planKey: string;
|
|
1372
1474
|
/** Resolved plan version, if known. */
|
|
@@ -1397,12 +1499,10 @@ interface CheckoutOfferRow {
|
|
|
1397
1499
|
updatedAt: string;
|
|
1398
1500
|
}
|
|
1399
1501
|
interface CheckoutOfferFilter {
|
|
1400
|
-
projectKey: string;
|
|
1401
1502
|
status?: CheckoutOfferStatus;
|
|
1402
1503
|
}
|
|
1403
1504
|
/** Body of `POST /public/checkout-offer` — called from the website. */
|
|
1404
1505
|
interface CreateCheckoutOfferData {
|
|
1405
|
-
projectKey: string;
|
|
1406
1506
|
planKey: string;
|
|
1407
1507
|
planVersionId?: string | null;
|
|
1408
1508
|
billingCycle: 'monthly' | 'yearly';
|
|
@@ -1438,7 +1538,6 @@ interface UpdateCheckoutOfferData {
|
|
|
1438
1538
|
|
|
1439
1539
|
/** Wire format of the `marketing_settings` row. */
|
|
1440
1540
|
interface MarketingSettingsRow {
|
|
1441
|
-
projectKey: string;
|
|
1442
1541
|
/** Runtime-activated subset of the `availableLocales` pool. */
|
|
1443
1542
|
activeLocales: string[];
|
|
1444
1543
|
updatedAt: string;
|
|
@@ -1556,7 +1655,6 @@ interface PublicComparisonRow {
|
|
|
1556
1655
|
}
|
|
1557
1656
|
/** Response of `GET /public/marketing-catalog`. */
|
|
1558
1657
|
interface PublicMarketingCatalogResponse {
|
|
1559
|
-
projectKey: string;
|
|
1560
1658
|
locale: string;
|
|
1561
1659
|
currency: string;
|
|
1562
1660
|
/** VAT rate in percent — for the CheckoutOffer price breakdown. */
|
|
@@ -1666,7 +1764,7 @@ interface DiscoverySnapshot {
|
|
|
1666
1764
|
/** ISO timestamp of the boot-time scan. */
|
|
1667
1765
|
scannedAt: string;
|
|
1668
1766
|
app: {
|
|
1669
|
-
/**
|
|
1767
|
+
/** The application's name, from `saas.yaml#app.name`. */
|
|
1670
1768
|
key: string;
|
|
1671
1769
|
/** Backend version, e.g. from package.json. */
|
|
1672
1770
|
version: string;
|
|
@@ -1838,7 +1936,6 @@ interface OnboardingPromoRedemption {
|
|
|
1838
1936
|
|
|
1839
1937
|
interface PlanRow {
|
|
1840
1938
|
id: string;
|
|
1841
|
-
projectKey: string;
|
|
1842
1939
|
planKey: string;
|
|
1843
1940
|
label: string;
|
|
1844
1941
|
description: string | null;
|
|
@@ -1855,7 +1952,6 @@ interface PlanRow {
|
|
|
1855
1952
|
* creation (follows in M6 Pack 2).
|
|
1856
1953
|
*/
|
|
1857
1954
|
interface CreatePlanData {
|
|
1858
|
-
projectKey: string;
|
|
1859
1955
|
planKey: string;
|
|
1860
1956
|
label: string;
|
|
1861
1957
|
description?: string | null;
|
|
@@ -1863,9 +1959,9 @@ interface CreatePlanData {
|
|
|
1863
1959
|
sortOrder?: number;
|
|
1864
1960
|
}
|
|
1865
1961
|
/**
|
|
1866
|
-
* Fields that may be changed on the plan stem. `planKey`
|
|
1867
|
-
*
|
|
1868
|
-
*
|
|
1962
|
+
* Fields that may be changed on the plan stem. `planKey` is deliberately not
|
|
1963
|
+
* here — stem identity is immutable; whoever wants to change it creates a new
|
|
1964
|
+
* plan and retires the old one.
|
|
1869
1965
|
*/
|
|
1870
1966
|
interface UpdatePlanData {
|
|
1871
1967
|
label?: string;
|
|
@@ -1929,7 +2025,6 @@ interface UpsertResult {
|
|
|
1929
2025
|
skipReason?: string;
|
|
1930
2026
|
}
|
|
1931
2027
|
interface UpsertPlanInput {
|
|
1932
|
-
projectKey: string;
|
|
1933
2028
|
planKey: string;
|
|
1934
2029
|
label: string;
|
|
1935
2030
|
description?: string | null;
|
|
@@ -1949,7 +2044,6 @@ interface UpsertPlanVersionInput {
|
|
|
1949
2044
|
changeNote: string;
|
|
1950
2045
|
}
|
|
1951
2046
|
interface UpsertFeatureCatalogEntryInput {
|
|
1952
|
-
projectKey: string;
|
|
1953
2047
|
featureKey: FeatureKey;
|
|
1954
2048
|
label?: string;
|
|
1955
2049
|
icon?: string;
|
|
@@ -1995,7 +2089,7 @@ interface PlanCatalogReadSnapshot {
|
|
|
1995
2089
|
* implement it against their Prisma tables.
|
|
1996
2090
|
*/
|
|
1997
2091
|
interface PlanCatalogReadSink {
|
|
1998
|
-
loadSnapshot(
|
|
2092
|
+
loadSnapshot(): Promise<PlanCatalogReadSnapshot>;
|
|
1999
2093
|
}
|
|
2000
2094
|
|
|
2001
2095
|
/**
|
|
@@ -2439,6 +2533,26 @@ interface PromoRevenueDeductionAggregator {
|
|
|
2439
2533
|
|
|
2440
2534
|
type ContractLineItemKind = 'plan' | 'bundle' | 'discount';
|
|
2441
2535
|
type SubscriptionContractStatus = 'active' | 'scheduled' | 'terminated' | 'superseded';
|
|
2536
|
+
/**
|
|
2537
|
+
* The statuses a contract is looked up under when asking "what is this tenant
|
|
2538
|
+
* on right now" — `scheduled` included, because a contract that starts today
|
|
2539
|
+
* and has not been switched to `active` yet is still the one in force at its
|
|
2540
|
+
* own `effectiveFrom`.
|
|
2541
|
+
*
|
|
2542
|
+
* One list rather than one per adapter: the two adapters have to answer
|
|
2543
|
+
* `findActiveByTenantId` the same way, and a status added here must not reach
|
|
2544
|
+
* only whichever of them somebody remembered.
|
|
2545
|
+
*/
|
|
2546
|
+
/**
|
|
2547
|
+
* How many bundle versions one price lookup may name.
|
|
2548
|
+
*
|
|
2549
|
+
* One number rather than two: the server validates against it and the client
|
|
2550
|
+
* batches to stay inside it, and a client that learned the cap by receiving a
|
|
2551
|
+
* 400 would fail silently — the lookup answers with an empty map, and every
|
|
2552
|
+
* card falls back to a catalogue price the tenant may not be charged.
|
|
2553
|
+
*/
|
|
2554
|
+
declare const BUNDLE_PRICE_LOOKUP_LIMIT = 200;
|
|
2555
|
+
declare const ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES: readonly SubscriptionContractStatus[];
|
|
2442
2556
|
interface ContractLineItemRecord {
|
|
2443
2557
|
id: string;
|
|
2444
2558
|
contractId: string;
|
|
@@ -2469,7 +2583,6 @@ interface SubscriptionContractPriceSnapshot {
|
|
|
2469
2583
|
}
|
|
2470
2584
|
interface SubscriptionContractRecord {
|
|
2471
2585
|
id: string;
|
|
2472
|
-
projectKey: string;
|
|
2473
2586
|
tenantId: string;
|
|
2474
2587
|
status: SubscriptionContractStatus;
|
|
2475
2588
|
effectiveFrom: Date;
|
|
@@ -2488,7 +2601,6 @@ interface SubscriptionContractRecord {
|
|
|
2488
2601
|
}
|
|
2489
2602
|
type NewContractLineItemData = Omit<ContractLineItemRecord, 'id' | 'contractId' | 'createdAt'>;
|
|
2490
2603
|
interface CreateSubscriptionContractData {
|
|
2491
|
-
projectKey: string;
|
|
2492
2604
|
tenantId: string;
|
|
2493
2605
|
status?: SubscriptionContractStatus;
|
|
2494
2606
|
effectiveFrom: Date;
|
|
@@ -2505,10 +2617,22 @@ interface CreateSubscriptionContractData {
|
|
|
2505
2617
|
}
|
|
2506
2618
|
interface TerminateSubscriptionContractData {
|
|
2507
2619
|
effectiveUntil: Date;
|
|
2508
|
-
|
|
2620
|
+
/**
|
|
2621
|
+
* The terminal status, or `null` to end the contract by date alone.
|
|
2622
|
+
*
|
|
2623
|
+
* `findActiveByTenantId` already asks its question as a window —
|
|
2624
|
+
* `effectiveFrom <= asOf` and `effectiveUntil` null or after it — so a
|
|
2625
|
+
* contract given an end in the FUTURE is found until that moment and not
|
|
2626
|
+
* afterwards, with no scheduled job to flip anything.
|
|
2627
|
+
*
|
|
2628
|
+
* Writing a terminal status instead makes the contract disappear from that
|
|
2629
|
+
* lookup at once, which for a cancellation declared months ahead removes an
|
|
2630
|
+
* agreement the customer is still under. Null is how a caller says "it ends
|
|
2631
|
+
* then", and a status is how it says "it is over now".
|
|
2632
|
+
*/
|
|
2633
|
+
status: Extract<SubscriptionContractStatus, 'terminated' | 'superseded'> | null;
|
|
2509
2634
|
}
|
|
2510
2635
|
interface SubscriptionContractFilter {
|
|
2511
|
-
projectKey?: string;
|
|
2512
2636
|
tenantId?: string;
|
|
2513
2637
|
status?: SubscriptionContractStatus;
|
|
2514
2638
|
asOf?: Date;
|
|
@@ -2530,7 +2654,6 @@ interface InvoiceLineItemSnapshot {
|
|
|
2530
2654
|
}
|
|
2531
2655
|
interface SubscriptionContractInvoiceSnapshot {
|
|
2532
2656
|
contractId: string;
|
|
2533
|
-
projectKey: string;
|
|
2534
2657
|
tenantId: string;
|
|
2535
2658
|
originalOfferId: string | null;
|
|
2536
2659
|
currency: string;
|
|
@@ -2564,6 +2687,24 @@ interface SubscriptionRecord {
|
|
|
2564
2687
|
} | null;
|
|
2565
2688
|
planVersionId: string;
|
|
2566
2689
|
planVersion: PlanVersionRecord;
|
|
2690
|
+
/**
|
|
2691
|
+
* When a cancellation was declared, and when it takes effect.
|
|
2692
|
+
*
|
|
2693
|
+
* Required, and required together, because entitlement resolution ends a
|
|
2694
|
+
* subscription by reading them: without the second date it cannot tell a
|
|
2695
|
+
* subscription that ends next January from one that ended last January, and
|
|
2696
|
+
* it grants the latter everything. Nothing else in the platform would
|
|
2697
|
+
* notice — no repository filters a cancelled subscription out, and stopping
|
|
2698
|
+
* the billing period is a different decision from ending what a tenant may
|
|
2699
|
+
* do.
|
|
2700
|
+
*
|
|
2701
|
+
* `null` on both means no cancellation. On a row written before the two
|
|
2702
|
+
* fields separated, `canceledAt` carries the effective date and
|
|
2703
|
+
* `canceledEffectiveAt` is genuinely null; every reader in the platform
|
|
2704
|
+
* applies `canceledEffectiveAt ?? canceledAt` for that reason.
|
|
2705
|
+
*/
|
|
2706
|
+
canceledAt: Date | null;
|
|
2707
|
+
canceledEffectiveAt: Date | null;
|
|
2567
2708
|
}
|
|
2568
2709
|
/** Snapshot of a `PlanVersion` row. */
|
|
2569
2710
|
interface PlanVersionRecord {
|
|
@@ -2620,11 +2761,10 @@ interface SubscriptionRepository {
|
|
|
2620
2761
|
countByBundleVersionId?(bundleVersionId: string): Promise<number>;
|
|
2621
2762
|
/**
|
|
2622
2763
|
* Counts active subscriptions (status `ACTIVE` or `TRIAL`) per plan key,
|
|
2623
|
-
* platform-wide across
|
|
2624
|
-
*
|
|
2764
|
+
* platform-wide across every tenant — feeds the tenant column of the
|
|
2765
|
+
* SuperAdmin plan list (`GET /admin/catalog/plans/tenant-counts`).
|
|
2625
2766
|
* Cross-version: counts the plan, not a single PlanVersion
|
|
2626
|
-
* (subscriptions on superseded versions are included).
|
|
2627
|
-
* informational for single-project consumers.
|
|
2767
|
+
* (subscriptions on superseded versions are included).
|
|
2628
2768
|
*
|
|
2629
2769
|
* Returns a map `planKey → count`; plans without an active subscription
|
|
2630
2770
|
* are missing (UI defaults to 0). Platform-wide count across all tenants →
|
|
@@ -2632,7 +2772,7 @@ interface SubscriptionRepository {
|
|
|
2632
2772
|
*
|
|
2633
2773
|
* Optional — if not implemented, the tenant column stays 0.
|
|
2634
2774
|
*/
|
|
2635
|
-
countActiveByPlanKey?(
|
|
2775
|
+
countActiveByPlanKey?(): Promise<Record<string, number>>;
|
|
2636
2776
|
}
|
|
2637
2777
|
/**
|
|
2638
2778
|
* Adapter for the `subscription_bundles` junction.
|
|
@@ -2724,6 +2864,40 @@ interface SubscriptionUsageRecord {
|
|
|
2724
2864
|
/** Current period window — for proration and change-effective date. */
|
|
2725
2865
|
currentPeriodStart: Date | null;
|
|
2726
2866
|
currentPeriodEnd: Date | null;
|
|
2867
|
+
/**
|
|
2868
|
+
* End of what was committed to, which the period end need not equal.
|
|
2869
|
+
*
|
|
2870
|
+
* The cancellation rules measure against this: a subscription cancelled
|
|
2871
|
+
* inside its term keeps running until the term ends, not until the period
|
|
2872
|
+
* does. Null on a trial, and on any subscription written before the field
|
|
2873
|
+
* existed — readers treat that as "the period end is the answer".
|
|
2874
|
+
*/
|
|
2875
|
+
minimumTermUntil?: Date | null;
|
|
2876
|
+
/**
|
|
2877
|
+
* The day of the month the subscription is billed on, 1–31.
|
|
2878
|
+
*
|
|
2879
|
+
* Read by the cancellation rules: a declaration after the notice window
|
|
2880
|
+
* lands one period past the term end, and that step has to measure from the
|
|
2881
|
+
* billing day rather than from a term end that may already have been
|
|
2882
|
+
* clamped by a short month.
|
|
2883
|
+
*
|
|
2884
|
+
* Optional, because an adapter that does not store the column keeps today's
|
|
2885
|
+
* behaviour — the step then takes its day from the term end, which is
|
|
2886
|
+
* correct except in the month after a clamp.
|
|
2887
|
+
*/
|
|
2888
|
+
billingAnchorDay?: number | null;
|
|
2889
|
+
/**
|
|
2890
|
+
* When a cancellation was declared, and when it lands.
|
|
2891
|
+
*
|
|
2892
|
+
* Required for the reason the same pair is required on
|
|
2893
|
+
* `SubscriptionRecord`: the tenant billing route reads them to refuse a
|
|
2894
|
+
* plan change on a subscription that has ended, and a record that omits
|
|
2895
|
+
* them answers "not cancelled" — so the change is applied and prorated
|
|
2896
|
+
* while entitlement resolution, which reads a record that does carry them,
|
|
2897
|
+
* grants nothing.
|
|
2898
|
+
*/
|
|
2899
|
+
canceledAt: Date | null;
|
|
2900
|
+
canceledEffectiveAt: Date | null;
|
|
2727
2901
|
pendingPlan: string | null;
|
|
2728
2902
|
pendingBillingCycle: string | null;
|
|
2729
2903
|
pendingEffectiveAt: Date | null;
|
|
@@ -2799,12 +2973,29 @@ interface ImmediatePlanChangeInput {
|
|
|
2799
2973
|
* change, or target package without trial). A `Date` is persisted.
|
|
2800
2974
|
*/
|
|
2801
2975
|
trialEndsAt?: Date | null;
|
|
2976
|
+
/**
|
|
2977
|
+
* `canceledAt` as the caller read it, so the write can claim the row only
|
|
2978
|
+
* while that is still true.
|
|
2979
|
+
*
|
|
2980
|
+
* Three of the plan route's decisions depend on the cancellation — whether
|
|
2981
|
+
* the change is refused at all, whether the billing cycle may move, and
|
|
2982
|
+
* whether a fresh period is opened — and a read and a write are two
|
|
2983
|
+
* moments. A cancellation declared in between made every one of them answer
|
|
2984
|
+
* about a state that no longer existed, and the write went ahead anyway: a
|
|
2985
|
+
* plan term recorded past the date the subscription ends.
|
|
2986
|
+
*
|
|
2987
|
+
* `null` is a value here rather than an absence. It claims a row that has
|
|
2988
|
+
* no cancellation, and loses against one that has acquired one.
|
|
2989
|
+
*/
|
|
2990
|
+
expectedCanceledAt: Date | null;
|
|
2802
2991
|
}
|
|
2803
2992
|
/** Input for `schedulePlanChange` (change at period end). */
|
|
2804
2993
|
interface ScheduledPlanChangeInput {
|
|
2805
2994
|
pendingPlan: string;
|
|
2806
2995
|
pendingBillingCycle: string;
|
|
2807
2996
|
pendingEffectiveAt: Date;
|
|
2997
|
+
/** See `ImmediatePlanChangeInput.expectedCanceledAt`. */
|
|
2998
|
+
expectedCanceledAt: Date | null;
|
|
2808
2999
|
}
|
|
2809
3000
|
/**
|
|
2810
3001
|
* Input for `applyOnboardingSelection`. Plan-change fields that the
|
|
@@ -2813,6 +3004,12 @@ interface ScheduledPlanChangeInput {
|
|
|
2813
3004
|
interface ApplyOnboardingSelectionInput {
|
|
2814
3005
|
planId: string;
|
|
2815
3006
|
cycle: string;
|
|
3007
|
+
/**
|
|
3008
|
+
* See `ImmediatePlanChangeInput.expectedCanceledAt`. The atomic path needs
|
|
3009
|
+
* it for the same reason the sequential one does: without it, the preferred
|
|
3010
|
+
* implementation is the one where the race stays open.
|
|
3011
|
+
*/
|
|
3012
|
+
expectedCanceledAt: Date | null;
|
|
2816
3013
|
/** For TRIAL → null, otherwise period start from `initialPeriodWindow`. */
|
|
2817
3014
|
periodStart: Date | null;
|
|
2818
3015
|
periodEnd: Date | null;
|
|
@@ -2829,6 +3026,12 @@ interface ApplyOnboardingSelectionResult {
|
|
|
2829
3026
|
subscriptionId: string;
|
|
2830
3027
|
/** null if no redeemPromo callback was provided or the callback returned null. */
|
|
2831
3028
|
promoRedemption: PromoCodeRedemptionRecord | null;
|
|
3029
|
+
/**
|
|
3030
|
+
* False when the row's cancellation moved since the caller read it, in
|
|
3031
|
+
* which case nothing was written — including the promo redemption, which
|
|
3032
|
+
* shares the transaction.
|
|
3033
|
+
*/
|
|
3034
|
+
claimed: boolean;
|
|
2832
3035
|
}
|
|
2833
3036
|
/**
|
|
2834
3037
|
* Callback signature for promo-code redemption WITHIN the onboarding
|
|
@@ -2846,14 +3049,46 @@ type RedeemPromoInTransactionCallback = (tx: TransactionContext, subscriptionId:
|
|
|
2846
3049
|
* app-specific. The platform service calls `invalidateTenant` in the
|
|
2847
3050
|
* EntitlementService after a successful adapter call.
|
|
2848
3051
|
*/
|
|
3052
|
+
/** What `cancelSubscription` is told to write. Named so both adapters spell
|
|
3053
|
+
* the same shape once rather than each restating it. */
|
|
3054
|
+
interface CancelSubscriptionInput {
|
|
3055
|
+
canceledAt: Date;
|
|
3056
|
+
effectiveAt: Date;
|
|
3057
|
+
terminateNow: boolean;
|
|
3058
|
+
minimumTermUntil?: Date;
|
|
3059
|
+
}
|
|
3060
|
+
/** What `cancelSubscription` answers with. */
|
|
3061
|
+
interface CancelSubscriptionResult {
|
|
3062
|
+
canceledAt: Date | null;
|
|
3063
|
+
canceledEffectiveAt: Date | null;
|
|
3064
|
+
status: string;
|
|
3065
|
+
/**
|
|
3066
|
+
* True when a cancellation was already recorded and this call changed
|
|
3067
|
+
* nothing — the stored dates are returned instead.
|
|
3068
|
+
*
|
|
3069
|
+
* The caller checks first, but a check and a write are two moments, and two
|
|
3070
|
+
* requests can pass the check before either writes. Straddling a notice
|
|
3071
|
+
* deadline that costs a billing cycle: the first declaration lands on time,
|
|
3072
|
+
* the second recomputes against a later `now`, and an unconditional write
|
|
3073
|
+
* replaces the first answer with one a period further out. An
|
|
3074
|
+
* implementation therefore claims the row only while both cancellation
|
|
3075
|
+
* fields are still empty, and answers `true` here when the claim finds
|
|
3076
|
+
* nothing to claim.
|
|
3077
|
+
*/
|
|
3078
|
+
alreadyCanceled: boolean;
|
|
3079
|
+
}
|
|
2849
3080
|
interface TenantSubscriptionWritePort {
|
|
2850
3081
|
/** Immediate change: set plan + cycle, clear pending fields, optionally reset the period. */
|
|
2851
3082
|
changePlanImmediate(tenantId: string, input: ImmediatePlanChangeInput): Promise<{
|
|
2852
3083
|
plan: string;
|
|
2853
3084
|
billingCycle: string;
|
|
3085
|
+
/** False when the row's cancellation moved since the caller read it. */
|
|
3086
|
+
claimed: boolean;
|
|
2854
3087
|
}>;
|
|
2855
3088
|
/** Change at period end: set pending fields. */
|
|
2856
|
-
schedulePlanChange(tenantId: string, input: ScheduledPlanChangeInput): Promise<
|
|
3089
|
+
schedulePlanChange(tenantId: string, input: ScheduledPlanChangeInput): Promise<{
|
|
3090
|
+
claimed: boolean;
|
|
3091
|
+
}>;
|
|
2857
3092
|
/**
|
|
2858
3093
|
* Marks the pending PlanVersion as accepted. Idempotent — a duplicate
|
|
2859
3094
|
* accept is a no-op. Returns `alreadyAccepted: true` if the status was
|
|
@@ -2866,13 +3101,30 @@ interface TenantSubscriptionWritePort {
|
|
|
2866
3101
|
alreadyAccepted: boolean;
|
|
2867
3102
|
}>;
|
|
2868
3103
|
/**
|
|
2869
|
-
*
|
|
2870
|
-
*
|
|
3104
|
+
* Record a cancellation. The dates are decided above this port.
|
|
3105
|
+
*
|
|
3106
|
+
* `canceledAt` is when the customer said it; `effectiveAt` is when it
|
|
3107
|
+
* lands. They differ for every ordinary cancellation, because a
|
|
3108
|
+
* subscription cancelled inside its term keeps running, keeps being billed
|
|
3109
|
+
* and keeps its entitlements until the term ends. An adapter that computed
|
|
3110
|
+
* the second from the first — which this one did, as
|
|
3111
|
+
* `immediate ? now : currentPeriodEnd` — was deciding a commercial
|
|
3112
|
+
* question in a persistence layer, and could not see the minimum term or
|
|
3113
|
+
* the notice period at all.
|
|
3114
|
+
*
|
|
3115
|
+
* `terminateNow` flips the status immediately, and is set when the
|
|
3116
|
+
* cancellation is already effective: an operator ending a contract, or the
|
|
3117
|
+
* rules finding nothing left to run — no period, no term, as on a trial.
|
|
3118
|
+
* It is never a client's request. A tenant may always declare a
|
|
3119
|
+
* cancellation and may never shorten the term they are in; what decides
|
|
3120
|
+
* this flag is the date the rules returned, not the date they asked for.
|
|
3121
|
+
*
|
|
3122
|
+
* `minimumTermUntil` extends the stored commitment, and is set only when
|
|
3123
|
+
* the cancellation itself extends it: a declaration made after the notice
|
|
3124
|
+
* deadline buys the following period. Left unset the stored term end is
|
|
3125
|
+
* unchanged, which is the ordinary case.
|
|
2871
3126
|
*/
|
|
2872
|
-
cancelSubscription(tenantId: string,
|
|
2873
|
-
canceledAt: Date | null;
|
|
2874
|
-
status: string;
|
|
2875
|
-
}>;
|
|
3127
|
+
cancelSubscription(tenantId: string, input: CancelSubscriptionInput): Promise<CancelSubscriptionResult>;
|
|
2876
3128
|
/**
|
|
2877
3129
|
* Atomic onboarding creation: sets plan + cycle + period window
|
|
2878
3130
|
* AND optionally calls a promo-redeem callback — all in a
|
|
@@ -3124,7 +3376,6 @@ interface RlsBypassPort {
|
|
|
3124
3376
|
|
|
3125
3377
|
/** Filter for `PlanRepository.list()`. */
|
|
3126
3378
|
interface PlanListFilter {
|
|
3127
|
-
projectKey: string;
|
|
3128
3379
|
/** Exclude soft-deleted plans — default `true`. */
|
|
3129
3380
|
excludeDeleted?: boolean;
|
|
3130
3381
|
/**
|
|
@@ -3158,7 +3409,7 @@ interface PlanListFilter {
|
|
|
3158
3409
|
interface PlanRepository {
|
|
3159
3410
|
list(filter: PlanListFilter): Promise<PlanRow[]>;
|
|
3160
3411
|
findById(planId: string): Promise<PlanRow | null>;
|
|
3161
|
-
findByKey(
|
|
3412
|
+
findByKey(planKey: string): Promise<PlanRow | null>;
|
|
3162
3413
|
create(data: CreatePlanData): Promise<PlanRow>;
|
|
3163
3414
|
update(planId: string, data: UpdatePlanData): Promise<PlanRow>;
|
|
3164
3415
|
/** Sets `deletedAt` to NOW(); soft-deleted plans are filtered from `list` by default. */
|
|
@@ -3259,10 +3510,24 @@ interface PlanRepository {
|
|
|
3259
3510
|
}
|
|
3260
3511
|
/** Filter for `BundleRepository.list()`. */
|
|
3261
3512
|
interface BundleListFilter {
|
|
3262
|
-
projectKey: string;
|
|
3263
3513
|
/** Exclude soft-deleted bundles — default `true`. */
|
|
3264
3514
|
excludeDeleted?: boolean;
|
|
3265
3515
|
}
|
|
3516
|
+
/**
|
|
3517
|
+
* What publishing a bundle draft records.
|
|
3518
|
+
*
|
|
3519
|
+
* Named because it was written out three times — the port, and each adapter's
|
|
3520
|
+
* implementation of it — and a signature restated is a contract restated: the
|
|
3521
|
+
* copies can drift, and nothing but a reader would notice.
|
|
3522
|
+
*/
|
|
3523
|
+
interface PublishBundleVersionMeta {
|
|
3524
|
+
publishedByUserId: string | null;
|
|
3525
|
+
publishedChanges: VersionChange[];
|
|
3526
|
+
nonRegressive: boolean;
|
|
3527
|
+
/** Required — validated by the service before the repository call. */
|
|
3528
|
+
validFrom: Date;
|
|
3529
|
+
validUntil: Date | null;
|
|
3530
|
+
}
|
|
3266
3531
|
/**
|
|
3267
3532
|
* Adapter for `Bundle` + `BundleVersion` persistence. Consumers implement
|
|
3268
3533
|
* this against their Prisma tables (`bundles` + `bundle_versions`).
|
|
@@ -3281,7 +3546,7 @@ interface BundleListFilter {
|
|
|
3281
3546
|
interface BundleRepository {
|
|
3282
3547
|
list(filter: BundleListFilter): Promise<BundleRow[]>;
|
|
3283
3548
|
findById(bundleId: string): Promise<BundleRow | null>;
|
|
3284
|
-
findByKey(
|
|
3549
|
+
findByKey(bundleKey: string): Promise<BundleRow | null>;
|
|
3285
3550
|
create(data: CreateBundleData): Promise<BundleRow>;
|
|
3286
3551
|
update(bundleId: string, data: UpdateBundleData): Promise<BundleRow>;
|
|
3287
3552
|
/** Sets `deletedAt` to NOW(); soft-deleted bundles are filtered from `list` by default. */
|
|
@@ -3340,14 +3605,7 @@ interface BundleRepository {
|
|
|
3340
3605
|
* if the predecessor carries a `validUntil` — the adapter only
|
|
3341
3606
|
* persists, it does not validate again.
|
|
3342
3607
|
*/
|
|
3343
|
-
publishDraft(versionId: string, publishMeta:
|
|
3344
|
-
publishedByUserId: string | null;
|
|
3345
|
-
publishedChanges: VersionChange[];
|
|
3346
|
-
nonRegressive: boolean;
|
|
3347
|
-
/** Required — validated by the service before the repository call. */
|
|
3348
|
-
validFrom: Date;
|
|
3349
|
-
validUntil: Date | null;
|
|
3350
|
-
}, tx?: TransactionContext): Promise<BundleVersionRow>;
|
|
3608
|
+
publishDraft(versionId: string, publishMeta: PublishBundleVersionMeta, tx?: TransactionContext): Promise<BundleVersionRow>;
|
|
3351
3609
|
/**
|
|
3352
3610
|
* Hard-discards a draft version (`publishedAt === null`) from the DB.
|
|
3353
3611
|
* Throws if the version was already published — published versions
|
|
@@ -3385,7 +3643,6 @@ interface MarketingProjectionRepository {
|
|
|
3385
3643
|
}
|
|
3386
3644
|
/** Upsert input for a capability from the discovery sync. */
|
|
3387
3645
|
interface UpsertCapabilityEntryData {
|
|
3388
|
-
projectKey: string;
|
|
3389
3646
|
capabilityKey: string;
|
|
3390
3647
|
label: string;
|
|
3391
3648
|
description: string | null;
|
|
@@ -3402,7 +3659,6 @@ interface UpsertCapabilityEntryData {
|
|
|
3402
3659
|
}
|
|
3403
3660
|
/** Upsert input for a feature from the discovery sync. */
|
|
3404
3661
|
interface UpsertFeatureEntryData {
|
|
3405
|
-
projectKey: string;
|
|
3406
3662
|
featureKey: string;
|
|
3407
3663
|
label: string;
|
|
3408
3664
|
description: string | null;
|
|
@@ -3416,7 +3672,6 @@ interface UpsertFeatureEntryData {
|
|
|
3416
3672
|
}
|
|
3417
3673
|
/** Upsert input for a quota from the discovery sync. */
|
|
3418
3674
|
interface UpsertQuotaEntryData {
|
|
3419
|
-
projectKey: string;
|
|
3420
3675
|
quotaKey: string;
|
|
3421
3676
|
label: string;
|
|
3422
3677
|
description: string | null;
|
|
@@ -3446,7 +3701,7 @@ interface SetCatalogEntryReviewData {
|
|
|
3446
3701
|
* Prisma tables.
|
|
3447
3702
|
*
|
|
3448
3703
|
* Binding:
|
|
3449
|
-
* - `upsert*` matches on
|
|
3704
|
+
* - `upsert*` matches on `<key>` and leaves `i18n`,
|
|
3450
3705
|
* `sortOrder`, `createdAt` as well as the approval fields (`approvedAt`/
|
|
3451
3706
|
* `approvedBy`/`approvedSignature`) **untouched** on an update —
|
|
3452
3707
|
* only the code-derived fields + the status (resolved by the service)
|
|
@@ -3462,7 +3717,7 @@ interface CatalogEntryRepository {
|
|
|
3462
3717
|
upsertCapability(data: UpsertCapabilityEntryData): Promise<CapabilityCatalogEntryRow>;
|
|
3463
3718
|
upsertFeature(data: UpsertFeatureEntryData): Promise<FeatureCatalogEntryRow>;
|
|
3464
3719
|
upsertQuota(data: UpsertQuotaEntryData): Promise<QuotaCatalogEntryRow>;
|
|
3465
|
-
retireMissing(
|
|
3720
|
+
retireMissing(type: 'capability' | 'feature' | 'quota', presentKeys: string[]): Promise<number>;
|
|
3466
3721
|
/**
|
|
3467
3722
|
* Sets or clears the successor pointer of a feature/quota
|
|
3468
3723
|
* (#39). The sync calls this when a key disappears from the snapshot
|
|
@@ -3471,17 +3726,17 @@ interface CatalogEntryRepository {
|
|
|
3471
3726
|
* adapters without a `successor_key` column omit the methods, and the sync
|
|
3472
3727
|
* then skips the pointers with a warn log.
|
|
3473
3728
|
*/
|
|
3474
|
-
setFeatureSuccessor?(
|
|
3475
|
-
setQuotaSuccessor?(
|
|
3476
|
-
findFeature(
|
|
3477
|
-
findQuota(
|
|
3478
|
-
setFeatureReview(
|
|
3479
|
-
setQuotaReview(
|
|
3480
|
-
setFeatureI18n(
|
|
3481
|
-
setQuotaI18n(
|
|
3729
|
+
setFeatureSuccessor?(featureKey: string, successorKey: string | null): Promise<FeatureCatalogEntryRow>;
|
|
3730
|
+
setQuotaSuccessor?(quotaKey: string, successorKey: string | null): Promise<QuotaCatalogEntryRow>;
|
|
3731
|
+
findFeature(featureKey: string): Promise<FeatureCatalogEntryRow | null>;
|
|
3732
|
+
findQuota(quotaKey: string): Promise<QuotaCatalogEntryRow | null>;
|
|
3733
|
+
setFeatureReview(featureKey: string, data: SetCatalogEntryReviewData): Promise<FeatureCatalogEntryRow>;
|
|
3734
|
+
setQuotaReview(quotaKey: string, data: SetCatalogEntryReviewData): Promise<QuotaCatalogEntryRow>;
|
|
3735
|
+
setFeatureI18n(featureKey: string, i18n: CatalogEntryI18n): Promise<FeatureCatalogEntryRow>;
|
|
3736
|
+
setQuotaI18n(quotaKey: string, i18n: CatalogEntryI18n): Promise<QuotaCatalogEntryRow>;
|
|
3482
3737
|
/** Sets the editable base fields (default locale `label`/`description`). */
|
|
3483
|
-
setFeatureBase(
|
|
3484
|
-
setQuotaBase(
|
|
3738
|
+
setFeatureBase(featureKey: string, data: UpdateCatalogEntryBaseData): Promise<FeatureCatalogEntryRow>;
|
|
3739
|
+
setQuotaBase(quotaKey: string, data: UpdateCatalogEntryBaseData): Promise<QuotaCatalogEntryRow>;
|
|
3485
3740
|
}
|
|
3486
3741
|
/**
|
|
3487
3742
|
* Adapter for `promotions`. **No versioning** — promotions are edited
|
|
@@ -3489,7 +3744,7 @@ interface CatalogEntryRepository {
|
|
|
3489
3744
|
* this against their `promotions` Prisma table.
|
|
3490
3745
|
*/
|
|
3491
3746
|
interface PromotionRepository {
|
|
3492
|
-
list(
|
|
3747
|
+
list(): Promise<PromotionRow[]>;
|
|
3493
3748
|
findById(id: string): Promise<PromotionRow | null>;
|
|
3494
3749
|
create(data: CreatePromotionData): Promise<PromotionRow>;
|
|
3495
3750
|
update(id: string, data: UpdatePromotionData): Promise<PromotionRow>;
|
|
@@ -3497,13 +3752,14 @@ interface PromotionRepository {
|
|
|
3497
3752
|
delete(id: string): Promise<void>;
|
|
3498
3753
|
}
|
|
3499
3754
|
/**
|
|
3500
|
-
* Adapter for `marketing_settings` — one row
|
|
3501
|
-
*
|
|
3502
|
-
*
|
|
3755
|
+
* Adapter for `marketing_settings` — at most one row, which a `CHECK` on the
|
|
3756
|
+
* canonical schema holds rather than convention. `get` returns `null` as long
|
|
3757
|
+
* as the SuperAdmin has saved nothing (then the full `availableLocales` pool
|
|
3758
|
+
* counts as active). `upsert` creates the row or replaces it.
|
|
3503
3759
|
*/
|
|
3504
3760
|
interface MarketingSettingsRepository {
|
|
3505
|
-
get(
|
|
3506
|
-
upsert(
|
|
3761
|
+
get(): Promise<MarketingSettingsRow | null>;
|
|
3762
|
+
upsert(data: UpdateMarketingSettingsData): Promise<MarketingSettingsRow>;
|
|
3507
3763
|
}
|
|
3508
3764
|
|
|
3509
3765
|
/**
|
|
@@ -3715,6 +3971,8 @@ declare const CATALOG_ERROR_CODES: {
|
|
|
3715
3971
|
readonly BUNDLE_VERSION_SUPERSEDED: "BUNDLE_VERSION_SUPERSEDED";
|
|
3716
3972
|
readonly BUNDLE_VERSION_REGRESSION: "BUNDLE_VERSION_REGRESSION";
|
|
3717
3973
|
readonly BUNDLE_VERSION_ZERO_PRICE: "BUNDLE_VERSION_ZERO_PRICE";
|
|
3974
|
+
readonly BUNDLE_VERSION_NO_PRICE: "BUNDLE_VERSION_NO_PRICE";
|
|
3975
|
+
readonly BUNDLE_VERSION_NOT_PRICED_FOR_PLAN: "BUNDLE_VERSION_NOT_PRICED_FOR_PLAN";
|
|
3718
3976
|
readonly BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED: "BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED";
|
|
3719
3977
|
readonly BUNDLE_VERSION_VALID_FROM_REQUIRED: "BUNDLE_VERSION_VALID_FROM_REQUIRED";
|
|
3720
3978
|
readonly BUNDLE_VERSION_VALID_FROM_INVALID: "BUNDLE_VERSION_VALID_FROM_INVALID";
|
|
@@ -3759,6 +4017,8 @@ declare const BILLING_ERROR_CODES: {
|
|
|
3759
4017
|
readonly BUNDLE_ALREADY_SUBSCRIBED: "BUNDLE_ALREADY_SUBSCRIBED";
|
|
3760
4018
|
readonly BUNDLE_INCOMPATIBLE_WITH_PLAN: "BUNDLE_INCOMPATIBLE_WITH_PLAN";
|
|
3761
4019
|
readonly BUNDLE_NOT_SELF_SERVICE: "BUNDLE_NOT_SELF_SERVICE";
|
|
4020
|
+
readonly BUNDLE_CYCLE_EXCEEDS_PLAN: "BUNDLE_CYCLE_EXCEEDS_PLAN";
|
|
4021
|
+
readonly BUNDLE_NOT_PRICED_FOR_THIS_PLAN: "BUNDLE_NOT_PRICED_FOR_THIS_PLAN";
|
|
3762
4022
|
readonly SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED: "SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED";
|
|
3763
4023
|
readonly SUBSCRIPTION_BUNDLE_NOT_CANCELLED: "SUBSCRIPTION_BUNDLE_NOT_CANCELLED";
|
|
3764
4024
|
readonly SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE: "SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE";
|
|
@@ -3915,6 +4175,8 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
3915
4175
|
readonly BUNDLE_ALREADY_SUBSCRIBED: "BUNDLE_ALREADY_SUBSCRIBED";
|
|
3916
4176
|
readonly BUNDLE_INCOMPATIBLE_WITH_PLAN: "BUNDLE_INCOMPATIBLE_WITH_PLAN";
|
|
3917
4177
|
readonly BUNDLE_NOT_SELF_SERVICE: "BUNDLE_NOT_SELF_SERVICE";
|
|
4178
|
+
readonly BUNDLE_CYCLE_EXCEEDS_PLAN: "BUNDLE_CYCLE_EXCEEDS_PLAN";
|
|
4179
|
+
readonly BUNDLE_NOT_PRICED_FOR_THIS_PLAN: "BUNDLE_NOT_PRICED_FOR_THIS_PLAN";
|
|
3918
4180
|
readonly SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED: "SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED";
|
|
3919
4181
|
readonly SUBSCRIPTION_BUNDLE_NOT_CANCELLED: "SUBSCRIPTION_BUNDLE_NOT_CANCELLED";
|
|
3920
4182
|
readonly SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE: "SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE";
|
|
@@ -3968,6 +4230,8 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
3968
4230
|
readonly BUNDLE_VERSION_SUPERSEDED: "BUNDLE_VERSION_SUPERSEDED";
|
|
3969
4231
|
readonly BUNDLE_VERSION_REGRESSION: "BUNDLE_VERSION_REGRESSION";
|
|
3970
4232
|
readonly BUNDLE_VERSION_ZERO_PRICE: "BUNDLE_VERSION_ZERO_PRICE";
|
|
4233
|
+
readonly BUNDLE_VERSION_NO_PRICE: "BUNDLE_VERSION_NO_PRICE";
|
|
4234
|
+
readonly BUNDLE_VERSION_NOT_PRICED_FOR_PLAN: "BUNDLE_VERSION_NOT_PRICED_FOR_PLAN";
|
|
3971
4235
|
readonly BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED: "BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED";
|
|
3972
4236
|
readonly BUNDLE_VERSION_VALID_FROM_REQUIRED: "BUNDLE_VERSION_VALID_FROM_REQUIRED";
|
|
3973
4237
|
readonly BUNDLE_VERSION_VALID_FROM_INVALID: "BUNDLE_VERSION_VALID_FROM_INVALID";
|
|
@@ -4786,6 +5050,98 @@ interface SetupConfirmMfaResponse {
|
|
|
4786
5050
|
ok: boolean;
|
|
4787
5051
|
}
|
|
4788
5052
|
|
|
5053
|
+
/** What the adapter's schema can actually answer about a version's dates. */
|
|
5054
|
+
interface PlanVersionMappingFields {
|
|
5055
|
+
/** `validFrom`/`validUntil` are maintained; otherwise both read as null. */
|
|
5056
|
+
validityWindows: boolean;
|
|
5057
|
+
/** `endsAt` exists; otherwise the field is left off the record entirely. */
|
|
5058
|
+
endsAt: boolean;
|
|
5059
|
+
}
|
|
5060
|
+
/** A `plans` row as either adapter reads it back. */
|
|
5061
|
+
interface CanonicalPlanRow {
|
|
5062
|
+
id: string;
|
|
5063
|
+
planKey: string;
|
|
5064
|
+
label: string;
|
|
5065
|
+
description: string | null;
|
|
5066
|
+
icon: string | null;
|
|
5067
|
+
sortOrder: number;
|
|
5068
|
+
createdAt: Date;
|
|
5069
|
+
updatedAt: Date;
|
|
5070
|
+
deletedAt: Date | null;
|
|
5071
|
+
}
|
|
5072
|
+
/** A `plan_versions` row as either adapter reads it back. */
|
|
5073
|
+
interface CanonicalPlanVersionRow {
|
|
5074
|
+
id: string;
|
|
5075
|
+
version: number;
|
|
5076
|
+
baseVersionId: string | null;
|
|
5077
|
+
features: unknown;
|
|
5078
|
+
quotas: unknown;
|
|
5079
|
+
monthlyNet: unknown;
|
|
5080
|
+
yearlyNet: unknown;
|
|
5081
|
+
marketed: boolean;
|
|
5082
|
+
publishedAt: Date | null;
|
|
5083
|
+
supersededAt: Date | null;
|
|
5084
|
+
publishedChanges: unknown;
|
|
5085
|
+
changeNote: string;
|
|
5086
|
+
nonRegressive: boolean;
|
|
5087
|
+
validFrom?: Date | null;
|
|
5088
|
+
validUntil?: Date | null;
|
|
5089
|
+
endsAt?: Date | null;
|
|
5090
|
+
createdByUserId: string | null;
|
|
5091
|
+
publishedByUserId: string | null;
|
|
5092
|
+
createdAt: Date;
|
|
5093
|
+
updatedAt: Date;
|
|
5094
|
+
}
|
|
5095
|
+
declare function toPlanRow(row: CanonicalPlanRow): PlanRow;
|
|
5096
|
+
/**
|
|
5097
|
+
* `planKey` is passed rather than read off the row: the canonical schema stores
|
|
5098
|
+
* the plan key in `planId`, but an adapter translating a consumer schema with a
|
|
5099
|
+
* real foreign key has to resolve it first, and only the adapter knows which
|
|
5100
|
+
* shape it is looking at.
|
|
5101
|
+
*/
|
|
5102
|
+
declare function toPlanVersionRow(row: CanonicalPlanVersionRow, planKey: string, fields: PlanVersionMappingFields): PlanVersionRow;
|
|
5103
|
+
|
|
5104
|
+
/** A `subscription_contracts` row as either adapter reads it back. */
|
|
5105
|
+
interface CanonicalContractRow {
|
|
5106
|
+
id: string;
|
|
5107
|
+
tenantId: string;
|
|
5108
|
+
status: string;
|
|
5109
|
+
effectiveFrom: Date;
|
|
5110
|
+
effectiveUntil: Date | null;
|
|
5111
|
+
originalOfferId: string | null;
|
|
5112
|
+
originalPlanVersionId: string | null;
|
|
5113
|
+
originalBundleVersionIds: unknown;
|
|
5114
|
+
entitlementSnapshot: unknown;
|
|
5115
|
+
priceSnapshot: unknown;
|
|
5116
|
+
promotionSnapshots: unknown;
|
|
5117
|
+
promoCodeSnapshots: unknown;
|
|
5118
|
+
termsSnapshot: unknown;
|
|
5119
|
+
createdAt: Date;
|
|
5120
|
+
updatedAt: Date;
|
|
5121
|
+
}
|
|
5122
|
+
/** A `contract_line_items` row as either adapter reads it back. */
|
|
5123
|
+
interface CanonicalContractLineItemRow {
|
|
5124
|
+
id: string;
|
|
5125
|
+
contractId: string;
|
|
5126
|
+
kind: string;
|
|
5127
|
+
sourceKey: string;
|
|
5128
|
+
sourceVersionId: string | null;
|
|
5129
|
+
titleSnapshot: string;
|
|
5130
|
+
descriptionSnapshot: string | null;
|
|
5131
|
+
quantity: number;
|
|
5132
|
+
unit: string | null;
|
|
5133
|
+
priceNet: unknown;
|
|
5134
|
+
priceGross: unknown;
|
|
5135
|
+
billingCycle: string;
|
|
5136
|
+
minimumTermUntil: Date | null;
|
|
5137
|
+
featuresSnapshot: unknown;
|
|
5138
|
+
quotaEffectsSnapshot: unknown;
|
|
5139
|
+
metadata: unknown;
|
|
5140
|
+
createdAt: Date;
|
|
5141
|
+
}
|
|
5142
|
+
declare function toSubscriptionContractRecord(row: CanonicalContractRow, lineItems: CanonicalContractLineItemRow[]): SubscriptionContractRecord;
|
|
5143
|
+
declare function toContractLineItemRecord(row: CanonicalContractLineItemRow): ContractLineItemRecord;
|
|
5144
|
+
|
|
4789
5145
|
/** Why a version is editable (for UI badges + audit logs). */
|
|
4790
5146
|
type VersionEditableReason = 'draft' | 'pre-active';
|
|
4791
5147
|
interface VersionEditability {
|
|
@@ -4826,4 +5182,4 @@ declare function resolveErrorMessage(body: Partial<PlatformErrorBody> & Record<s
|
|
|
4826
5182
|
|
|
4827
5183
|
declare const ERROR_MESSAGES_DE: Record<PlatformErrorCode, string>;
|
|
4828
5184
|
|
|
4829
|
-
export { AUTH_ERROR_CODES, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminResourcesPort, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminUserListFilter, type AdminUserListRow, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionRow, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, type CancelSubscriptionBundleData, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferStatus, type CheckoutSession, type CleanupResult, type CliUserRow, type ComponentKey, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ContractErrorCode, type ContractLineItemKind, type ContractLineItemRecord, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EffectiveLimitsSnapshot, type ErrorMessageParams, FEATURE_NOT_LICENSED, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FinalActivationResult, type FirstTimeCustomerCheck, type HandlePaymentEventInput, type HandlePaymentEventReason, type HandlePaymentEventResult, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type KpiCardDef, type KpiDisplayHint, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MfaPort, type NewContractLineItemData, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, PASSWORD_RESET_TTL_MINUTES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PasswordHasher, type PasswordResetCliResult, type PaymentEventLog, type PaymentEventStatus, type PaymentProvider, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, 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 PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionFilter, type PromotionI18n, type PromotionI18nFields, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicSignupPlan, type PublishBundleVersionData, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, type ReassignTenantAdminCliResult, type RedeemPromoInTransactionCallback, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type RequiredCapabilities, type ResumeRegistrationInput, type ResumeRegistrationResult, type ReviewCatalogEntryData, type RlsBypassPort, SETUP_ERROR_CODES, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledPlanChangeInput, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SetCatalogEntryReviewData, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartRegistrationInput, type StartRegistrationResult, type StrictModeWarning, type StrictModeWarningCode, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SyncDiscoveryResult, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, classifyBundleVersionDiff, classifyPlanDiff, collectUnsatisfiedRequires, coverageExcludingSelf, formatErrorMessage, isBundleRedundant, isPlatformUserExistsError, isVersionEditable, missingRequiresFor, pickActivePromo, promoStatus, resolveBundleAvailability, resolveErrorMessage, selectChargeableBundles, startOfUtcDay };
|
|
5185
|
+
export { ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES, AUTH_ERROR_CODES, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminResourcesPort, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminUserListFilter, type AdminUserListRow, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BUNDLE_PRICE_LOOKUP_LIMIT, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionRow, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferStatus, type CheckoutSession, type CleanupResult, type CliUserRow, type ComponentKey, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ContractErrorCode, type ContractLineItemKind, type ContractLineItemRecord, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EffectiveLimitsSnapshot, type ErrorMessageParams, FEATURE_NOT_LICENSED, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FinalActivationResult, type FirstTimeCustomerCheck, type HandlePaymentEventInput, type HandlePaymentEventReason, type HandlePaymentEventResult, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type KpiCardDef, type KpiDisplayHint, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MfaPort, type NewContractLineItemData, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, PASSWORD_RESET_TTL_MINUTES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PasswordHasher, type PasswordResetCliResult, type PaymentEventLog, type PaymentEventStatus, type PaymentProvider, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMappingFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionI18n, type PromotionI18nFields, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicSignupPlan, type PublishBundleVersionData, type PublishBundleVersionMeta, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, type ReassignTenantAdminCliResult, type RedeemPromoInTransactionCallback, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type RequiredCapabilities, type ResumeRegistrationInput, type ResumeRegistrationResult, type ReviewCatalogEntryData, type RlsBypassPort, SETUP_ERROR_CODES, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledPlanChangeInput, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SetCatalogEntryReviewData, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SyncDiscoveryResult, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleStemDefaults, classifyBundleVersionDiff, classifyPlanDiff, collectUnsatisfiedRequires, coverageExcludingSelf, definedFields, formatErrorMessage, isBundleRedundant, isPlatformUserExistsError, isVersionEditable, missingRequiresFor, pickActivePromo, previousUtcDay, promoStatus, resolveBundleAvailability, resolveErrorMessage, selectChargeableBundles, startOfUtcDay, toBundleStemRow, toContractLineItemRecord, toPlanRow, toPlanVersionRow, toSubscriptionContractRecord };
|