@saasicat/nest 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/_entries.cjs +1309 -519
  2. package/dist/admin/index.js +1 -1
  3. package/dist/billing/index.d.cts +7 -4
  4. package/dist/billing/index.d.ts +7 -4
  5. package/dist/billing/index.js +6 -6
  6. package/dist/catalog/index.js +4 -4
  7. package/dist/checkout-offer/index.js +2 -2
  8. package/dist/{chunk-Z3FWN3HJ.js → chunk-5ZXBXYXU.js} +3 -3
  9. package/dist/{chunk-RZVSKKXX.js → chunk-6WA4X5U3.js} +46 -45
  10. package/dist/{chunk-V34AA7C7.js → chunk-6WL6VQ7Z.js} +1 -1
  11. package/dist/{chunk-ABB2CRAS.js → chunk-74SCJ4HF.js} +1 -1
  12. package/dist/{chunk-PLJEAUFU.js → chunk-7JIHG53V.js} +76 -39
  13. package/dist/{chunk-7RRWI5LH.js → chunk-AFK2IE2L.js} +10 -10
  14. package/dist/{chunk-32EMXPU2.js → chunk-B7NRY2LV.js} +48 -17
  15. package/dist/{chunk-MDIZUVIK.js → chunk-BSK6YBLI.js} +1 -1
  16. package/dist/{chunk-R2QOSVAA.js → chunk-DQKCK7DX.js} +1 -1
  17. package/dist/{chunk-GLLCB4BP.js → chunk-EUU3B6NB.js} +17 -13
  18. package/dist/{chunk-EXOLOJFZ.js → chunk-F6DCLVBB.js} +29 -8
  19. package/dist/{chunk-5KH2O4SF.js → chunk-I77VS3YH.js} +287 -105
  20. package/dist/{chunk-YITTE646.js → chunk-KUDKD7ZG.js} +34 -14
  21. package/dist/{chunk-P3DP6GJE.js → chunk-LXUBCLRK.js} +486 -160
  22. package/dist/{chunk-GJBXOCRZ.js → chunk-ORWIGSNN.js} +45 -17
  23. package/dist/{chunk-E7AJ42AB.js → chunk-QLJHIIOY.js} +168 -28
  24. package/dist/{chunk-BOADBIGB.js → chunk-YYUXKLXK.js} +2 -2
  25. package/dist/{define-saasicat-Rc0rXrYG.d.ts → define-saasicat-CqkhnHn-.d.ts} +1 -1
  26. package/dist/{define-saasicat-CeDBX9ji.d.cts → define-saasicat-D8c6Bs4T.d.cts} +1 -1
  27. package/dist/discovery/index.d.cts +2 -2
  28. package/dist/discovery/index.d.ts +2 -2
  29. package/dist/discovery/index.js +4 -4
  30. package/dist/{enforce-quota.interceptor-DMw-bPyk.d.cts → enforce-quota.interceptor-Dk0eEtzV.d.cts} +1 -1
  31. package/dist/{enforce-quota.interceptor-CmbWX39L.d.ts → enforce-quota.interceptor-Dp8wTYro.d.ts} +1 -1
  32. package/dist/entitlement/index.js +2 -2
  33. package/dist/index.d.cts +6 -6
  34. package/dist/index.d.ts +6 -6
  35. package/dist/index.js +17 -17
  36. package/dist/{module-DgYJur6f.d.ts → module-BwD-wAor.d.ts} +1 -1
  37. package/dist/{module-CSN8j8Tp.d.cts → module-DsDkbawm.d.cts} +1 -1
  38. package/dist/platform/index.d.cts +8 -8
  39. package/dist/platform/index.d.ts +8 -8
  40. package/dist/platform/index.js +13 -13
  41. package/dist/promo/index.d.cts +3 -3
  42. package/dist/promo/index.d.ts +3 -3
  43. package/dist/promo/index.js +3 -3
  44. package/dist/registration/index.js +1 -1
  45. package/dist/{saas-platform.module-DLhoqKNA.d.ts → saas-platform.module-BQmrDGVU.d.ts} +1 -1
  46. package/dist/{saas-platform.module-D3rUTiho.d.cts → saas-platform.module-DducnQ9s.d.cts} +1 -1
  47. package/dist/{service-DX8KbGXl.d.cts → service-DPZ2W1E-.d.cts} +2 -2
  48. package/dist/{service-DX8KbGXl.d.ts → service-DPZ2W1E-.d.ts} +2 -2
  49. package/dist/subscription-contract/index.js +2 -2
  50. package/dist/{tenant-billing.controller-BwZRnJ3q.d.ts → tenant-billing.controller-b1G1yB09.d.ts} +2 -2
  51. package/dist/{tenant-billing.controller-CG4CaFUP.d.cts → tenant-billing.controller-m42YQ_Ei.d.cts} +2 -2
  52. package/dist/testing/index.d.cts +5 -5
  53. package/dist/testing/index.d.ts +5 -5
  54. package/dist/testing/index.js +33 -33
  55. package/package.json +3 -3
@@ -25,7 +25,7 @@ import {
25
25
  SuperAdminGuard,
26
26
  SuspendTenantDto,
27
27
  buildAdminStatsController
28
- } from "../chunk-PLJEAUFU.js";
28
+ } from "../chunk-7JIHG53V.js";
29
29
  import {
30
30
  AUDIT_PORT_TOKEN,
31
31
  AdminAuditService,
@@ -8,10 +8,10 @@ import { c as EntitlementService } from '../aggregation-SKfXu09x.cjs';
8
8
  import { P as ProviderSpec } from '../di-CcNeq9v-.cjs';
9
9
  import { f as ContractFreezePort, g as ContractFreezeSourcePort } from '../subscription-bundles.module-DCpV-Pb5.cjs';
10
10
  export { A as AUDIT_CONTEXT_RESOLVER_TOKEN, a as AuditContextResolver, b as AuthGuardList, C as CONTRACT_FREEZE_PORT_TOKEN, c as CONTRACT_FREEZE_PROJECT_KEY_TOKEN, d as CONTRACT_FREEZE_SOURCE_PORT_TOKEN, e as ContractFreezeBundleSnapshot, D as DuePendingPlanChange, P as PENDING_PLAN_QUERY_PORT_TOKEN, h as PendingPlanQueryPort, S as SELF_SERVICE_BLOCKED_BUNDLES_TOKEN, i as SELF_SERVICE_BLOCKED_PLANS_TOKEN, j as SUBSCRIPTION_USAGE_PORT_TOKEN, k as SUBSCRIPTION_WRITE_PORT_TOKEN, l as SelfServiceBlockedBundles, m as SelfServiceBlockedPlans, n as SubscriptionBundleControllerOptions, o as SubscriptionBundleModule, p as SubscriptionBundleModuleOptions, T as TENANT_AUTH_GUARDS_TOKEN, q as TENANT_ID_RESOLVER_TOKEN, r as TRIAL_PROJECTION_PORT_TOKEN, s as TenantBillingModule, t as TenantBillingModuleOptions, u as TenantIdResolver, v as TrialProjectionInput, w as TrialProjectionPort, U as USAGE_SNAPSHOT_PORT_TOKEN, x as USER_EMAIL_RESOLVER_TOKEN, y as USER_ID_RESOLVER_TOKEN, z as UserEmailResolver, B as UserIdResolver } from '../subscription-bundles.module-DCpV-Pb5.cjs';
11
- export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from '../tenant-billing.controller-CG4CaFUP.cjs';
11
+ export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from '../tenant-billing.controller-m42YQ_Ei.cjs';
12
12
  import { S as SubscriptionContractService } from '../subscription-contract.service--cm47ZJJ.cjs';
13
13
  import '../plan-resolution-CFCoUkrE.cjs';
14
- import '../service-DX8KbGXl.cjs';
14
+ import '../service-DPZ2W1E-.cjs';
15
15
  import '../admin-audit.service-9IqXMlZm.cjs';
16
16
 
17
17
  /**
@@ -199,13 +199,16 @@ declare class FeatureGuard implements CanActivate {
199
199
  /**
200
200
  * Upsell response (#36): with a registered `UpsellOfferResolver` the 403
201
201
  * becomes machine-readable (`FeatureNotLicensedBody`), so consumer UIs can
202
- * render a purchase offer. Without a resolver the previous plain 403
203
- * remains no breaking change.
202
+ * render a purchase offer. Without a resolver the body carries the same
203
+ * `code` but no offers.
204
204
  *
205
205
  * Deliberately 403 + `code` field instead of 402 — rationale in
206
206
  * `@saasicat/types` upsell.types.ts (402 is reserved / inconsistently
207
207
  * supported; SPA interceptors must not treat the 403 as an auth error, the
208
208
  * distinction runs through `code`).
209
+ *
210
+ * The message must keep starting with the word `Feature` — consumers
211
+ * classify the response by that prefix.
209
212
  */
210
213
  private buildNotLicensedException;
211
214
  /**
@@ -8,10 +8,10 @@ import { c as EntitlementService } from '../aggregation-o0LMenvl.js';
8
8
  import { P as ProviderSpec } from '../di-CcNeq9v-.js';
9
9
  import { f as ContractFreezePort, g as ContractFreezeSourcePort } from '../subscription-bundles.module-BQmoozm5.js';
10
10
  export { A as AUDIT_CONTEXT_RESOLVER_TOKEN, a as AuditContextResolver, b as AuthGuardList, C as CONTRACT_FREEZE_PORT_TOKEN, c as CONTRACT_FREEZE_PROJECT_KEY_TOKEN, d as CONTRACT_FREEZE_SOURCE_PORT_TOKEN, e as ContractFreezeBundleSnapshot, D as DuePendingPlanChange, P as PENDING_PLAN_QUERY_PORT_TOKEN, h as PendingPlanQueryPort, S as SELF_SERVICE_BLOCKED_BUNDLES_TOKEN, i as SELF_SERVICE_BLOCKED_PLANS_TOKEN, j as SUBSCRIPTION_USAGE_PORT_TOKEN, k as SUBSCRIPTION_WRITE_PORT_TOKEN, l as SelfServiceBlockedBundles, m as SelfServiceBlockedPlans, n as SubscriptionBundleControllerOptions, o as SubscriptionBundleModule, p as SubscriptionBundleModuleOptions, T as TENANT_AUTH_GUARDS_TOKEN, q as TENANT_ID_RESOLVER_TOKEN, r as TRIAL_PROJECTION_PORT_TOKEN, s as TenantBillingModule, t as TenantBillingModuleOptions, u as TenantIdResolver, v as TrialProjectionInput, w as TrialProjectionPort, U as USAGE_SNAPSHOT_PORT_TOKEN, x as USER_EMAIL_RESOLVER_TOKEN, y as USER_ID_RESOLVER_TOKEN, z as UserEmailResolver, B as UserIdResolver } from '../subscription-bundles.module-BQmoozm5.js';
11
- export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from '../tenant-billing.controller-BwZRnJ3q.js';
11
+ export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from '../tenant-billing.controller-b1G1yB09.js';
12
12
  import { S as SubscriptionContractService } from '../subscription-contract.service--cm47ZJJ.js';
13
13
  import '../plan-resolution-CFCoUkrE.js';
14
- import '../service-DX8KbGXl.js';
14
+ import '../service-DPZ2W1E-.js';
15
15
  import '../admin-audit.service-9IqXMlZm.js';
16
16
 
17
17
  /**
@@ -199,13 +199,16 @@ declare class FeatureGuard implements CanActivate {
199
199
  /**
200
200
  * Upsell response (#36): with a registered `UpsellOfferResolver` the 403
201
201
  * becomes machine-readable (`FeatureNotLicensedBody`), so consumer UIs can
202
- * render a purchase offer. Without a resolver the previous plain 403
203
- * remains no breaking change.
202
+ * render a purchase offer. Without a resolver the body carries the same
203
+ * `code` but no offers.
204
204
  *
205
205
  * Deliberately 403 + `code` field instead of 402 — rationale in
206
206
  * `@saasicat/types` upsell.types.ts (402 is reserved / inconsistently
207
207
  * supported; SPA interceptors must not treat the 403 as an auth error, the
208
208
  * distinction runs through `code`).
209
+ *
210
+ * The message must keep starting with the word `Feature` — consumers
211
+ * classify the response by that prefix.
209
212
  */
210
213
  private buildNotLicensedException;
211
214
  /**
@@ -58,9 +58,9 @@ import {
58
58
  periodEndWithMinLead,
59
59
  resolveBundleCancelEffectiveAt,
60
60
  resolveBundlePriceNet
61
- } from "../chunk-5KH2O4SF.js";
62
- import "../chunk-E7AJ42AB.js";
63
- import "../chunk-32EMXPU2.js";
61
+ } from "../chunk-I77VS3YH.js";
62
+ import "../chunk-QLJHIIOY.js";
63
+ import "../chunk-B7NRY2LV.js";
64
64
  import {
65
65
  AUDIT_CONTEXT_RESOLVER_TOKEN,
66
66
  PENDING_PLAN_QUERY_PORT_TOKEN,
@@ -76,12 +76,12 @@ import {
76
76
  classifyPlanDiff
77
77
  } from "../chunk-WPUVJRIN.js";
78
78
  import "../chunk-E56W4U2P.js";
79
- import "../chunk-MDIZUVIK.js";
79
+ import "../chunk-BSK6YBLI.js";
80
80
  import "../chunk-YSC46BGM.js";
81
81
  import {
82
82
  SUBSCRIPTION_BUNDLE_CONFIG_TOKEN,
83
83
  SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN
84
- } from "../chunk-EXOLOJFZ.js";
84
+ } from "../chunk-F6DCLVBB.js";
85
85
  import {
86
86
  PLAN_CATALOG_READ_SINK_TOKEN,
87
87
  PLAN_CATALOG_TOKEN,
@@ -96,7 +96,7 @@ import {
96
96
  getPlanQuota,
97
97
  isFeatureInPlan,
98
98
  isFeaturePlannedOnly
99
- } from "../chunk-R2QOSVAA.js";
99
+ } from "../chunk-DQKCK7DX.js";
100
100
  import "../chunk-NYLON2VC.js";
101
101
  import "../chunk-WKVBNTYC.js";
102
102
  import "../chunk-L4KTQ6CL.js";
@@ -6,8 +6,8 @@ import {
6
6
  runSeedGateFromFile,
7
7
  seedGateExitCode,
8
8
  validateSeedAgainstSnapshot
9
- } from "../chunk-7RRWI5LH.js";
10
- import "../chunk-ABB2CRAS.js";
9
+ } from "../chunk-AFK2IE2L.js";
10
+ import "../chunk-74SCJ4HF.js";
11
11
  import {
12
12
  ADVISORY_STRICT_MODE_CODES,
13
13
  BundlesService,
@@ -56,11 +56,11 @@ import {
56
56
  quotaApprovalSignature,
57
57
  validateBundleDraft,
58
58
  validatePlanDraft
59
- } from "../chunk-P3DP6GJE.js";
59
+ } from "../chunk-LXUBCLRK.js";
60
60
  import "../chunk-WPUVJRIN.js";
61
61
  import "../chunk-E56W4U2P.js";
62
62
  import "../chunk-YSC46BGM.js";
63
- import "../chunk-Z3FWN3HJ.js";
63
+ import "../chunk-5ZXBXYXU.js";
64
64
  import "../chunk-WKVBNTYC.js";
65
65
  import {
66
66
  BUNDLE_REPOSITORY_TOKEN,
@@ -6,8 +6,8 @@ import {
6
6
  CreateCheckoutOfferDto,
7
7
  UpdateCheckoutOfferDto,
8
8
  buildCheckoutOfferController
9
- } from "../chunk-GJBXOCRZ.js";
10
- import "../chunk-MDIZUVIK.js";
9
+ } from "../chunk-ORWIGSNN.js";
10
+ import "../chunk-BSK6YBLI.js";
11
11
  import "../chunk-YSC46BGM.js";
12
12
  import "../chunk-L4KTQ6CL.js";
13
13
  import "../chunk-SABTXESR.js";
@@ -74,7 +74,7 @@ var DiscoveryScanner = class _DiscoveryScanner {
74
74
  writeFileSync(path, JSON.stringify(snapshot, null, 2) + "\n", "utf-8");
75
75
  this.logger.log(`Discovery snapshot persisted to ${path}`);
76
76
  } catch (err) {
77
- this.logger.warn(`Discovery snapshot konnte nicht nach ${path} geschrieben werden: ${err.message}`);
77
+ this.logger.warn(`The discovery snapshot could not be written to ${path}: ${err.message}`);
78
78
  }
79
79
  }
80
80
  /**
@@ -159,7 +159,7 @@ var DiscoveryScanner = class _DiscoveryScanner {
159
159
  registerCapability(target, meta, declaredAt) {
160
160
  const existing = target.get(meta.capabilityKey);
161
161
  if (existing) {
162
- this.logger.warn(`Capability '${meta.capabilityKey}' wird an mehreren Stellen deklariert (${existing.declaredAt} und ${declaredAt}); erste Deklaration gewinnt`);
162
+ this.logger.warn(`Capability '${meta.capabilityKey}' is declared in several places (${existing.declaredAt} and ${declaredAt}); the first declaration wins`);
163
163
  return;
164
164
  }
165
165
  target.set(meta.capabilityKey, {
@@ -180,7 +180,7 @@ var DiscoveryScanner = class _DiscoveryScanner {
180
180
  registerQuota(target, opts, declaredAt) {
181
181
  const existing = target.get(opts.key);
182
182
  if (existing) {
183
- this.logger.warn(`Quota '${opts.key}' wird an mehreren Stellen definiert (${existing.declaredAt} und ${declaredAt}); erste Definition gewinnt`);
183
+ this.logger.warn(`Quota '${opts.key}' is defined in several places (${existing.declaredAt} and ${declaredAt}); the first definition wins`);
184
184
  return;
185
185
  }
186
186
  target.set(opts.key, {
@@ -54,7 +54,7 @@ var REGISTRATION_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/Regist
54
54
 
55
55
  // src/registration/pending-registration.service.ts
56
56
  import { BadRequestException, Inject, Injectable, Logger, NotFoundException, Optional } from "@nestjs/common";
57
- import { REGISTRATION_RESUME_TTL_MINUTES } from "@saasicat/types";
57
+ import { REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES } from "@saasicat/types";
58
58
  import { OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, REGISTRATION_STEP_BY_STATUS } from "@saasicat/types";
59
59
 
60
60
  // src/registration/pricing.ts
@@ -173,7 +173,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
173
173
  });
174
174
  } catch (error) {
175
175
  const message = error instanceof Error ? error.message : String(error);
176
- this.logger.warn(`Audit-Log fehlgeschlagen (${eventType}): ${message}`);
176
+ this.logger.warn(`Audit log write failed (${eventType}): ${message}`);
177
177
  }
178
178
  }
179
179
  /** Public signup plan list for step 3 (frontend `usePublicPlans()`). */
@@ -184,23 +184,23 @@ var PendingRegistrationService = class _PendingRegistrationService {
184
184
  const pending = await this.repo.findById(input.pendingRegistrationId);
185
185
  if (!pending) {
186
186
  throw new NotFoundException({
187
- code: "PENDING_REGISTRATION_NOT_FOUND"
187
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_NOT_FOUND
188
188
  });
189
189
  }
190
190
  if (pending.expiresAt.getTime() < Date.now()) {
191
191
  throw new BadRequestException({
192
- code: "PENDING_REGISTRATION_EXPIRED"
192
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_EXPIRED
193
193
  });
194
194
  }
195
195
  if (pending.status !== "EMAIL_VERIFIED" && pending.status !== "PLAN_SELECTED" && pending.status !== "CHECKOUT_STARTED") {
196
196
  throw new BadRequestException({
197
- code: "INVALID_REGISTRATION_STATE"
197
+ code: REGISTRATION_ERROR_CODES.INVALID_REGISTRATION_STATE
198
198
  });
199
199
  }
200
200
  const plan = await this.planCatalog.findPublicSignupPlan(input.planId);
201
201
  if (!plan) {
202
202
  throw new BadRequestException({
203
- code: "PLAN_NOT_AVAILABLE"
203
+ code: REGISTRATION_ERROR_CODES.PLAN_NOT_AVAILABLE
204
204
  });
205
205
  }
206
206
  const now = /* @__PURE__ */ new Date();
@@ -225,28 +225,28 @@ var PendingRegistrationService = class _PendingRegistrationService {
225
225
  const pending = await this.repo.findById(input.pendingRegistrationId);
226
226
  if (!pending) {
227
227
  throw new NotFoundException({
228
- code: "PENDING_REGISTRATION_NOT_FOUND"
228
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_NOT_FOUND
229
229
  });
230
230
  }
231
231
  if (pending.expiresAt.getTime() < Date.now()) {
232
232
  throw new BadRequestException({
233
- code: "PENDING_REGISTRATION_EXPIRED"
233
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_EXPIRED
234
234
  });
235
235
  }
236
236
  if (pending.status !== "PLAN_SELECTED" && pending.status !== "CHECKOUT_STARTED") {
237
237
  throw new BadRequestException({
238
- code: "PLAN_NOT_SELECTED"
238
+ code: REGISTRATION_ERROR_CODES.PLAN_NOT_SELECTED
239
239
  });
240
240
  }
241
241
  if (!pending.selectedPlanId) {
242
242
  throw new BadRequestException({
243
- code: "PLAN_NOT_SELECTED"
243
+ code: REGISTRATION_ERROR_CODES.PLAN_NOT_SELECTED
244
244
  });
245
245
  }
246
246
  const plan = await this.planCatalog.findPublicSignupPlan(pending.selectedPlanId);
247
247
  if (!plan) {
248
248
  throw new BadRequestException({
249
- code: "PLAN_NOT_AVAILABLE"
249
+ code: REGISTRATION_ERROR_CODES.PLAN_NOT_AVAILABLE
250
250
  });
251
251
  }
252
252
  const session = await this.paymentProvider.createCheckoutSession({
@@ -298,7 +298,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
298
298
  rawPayload: input.rawPayload
299
299
  });
300
300
  if (!claimed) {
301
- this.logger.warn(`Idempotenz: PaymentEvent ${input.eventId} bereits verarbeitet \u2014 Duplikat verworfen.`);
301
+ this.logger.warn(`Idempotency: payment event ${input.eventId} already processed \u2014 duplicate discarded.`);
302
302
  await this.record("PAYMENT_DUPLICATE_IGNORED", null, context, {
303
303
  eventId: input.eventId,
304
304
  sessionId: input.sessionId
@@ -348,7 +348,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
348
348
  tenantId: result.tenantId,
349
349
  subscriptionId: result.subscriptionId
350
350
  });
351
- this.logger.log(`Aktivierung erfolgreich: pending=${pending.id} \u2192 user=${result.userId} tenant=${result.tenantId} subscription=${result.subscriptionId}`);
351
+ this.logger.log(`Activation succeeded: pending=${pending.id} \u2192 user=${result.userId} tenant=${result.tenantId} subscription=${result.subscriptionId}`);
352
352
  return {
353
353
  activated: true,
354
354
  result
@@ -376,11 +376,11 @@ var PendingRegistrationService = class _PendingRegistrationService {
376
376
  await this.repo.delete(pending.id);
377
377
  } catch (error) {
378
378
  const message = error instanceof Error ? error.message : String(error);
379
- this.logger.warn(`Cleanup: PendingRegistration ${pending.id} konnte nicht geloescht werden (${message}).`);
379
+ this.logger.warn(`Cleanup: pending registration ${pending.id} could not be deleted (${message}).`);
380
380
  }
381
381
  }
382
382
  if (expired.length > 0) {
383
- this.logger.log(`Cleanup: ${expired.length} abgelaufene PendingRegistrations geloescht.`);
383
+ this.logger.log(`Cleanup: ${expired.length} expired PendingRegistrations deleted.`);
384
384
  }
385
385
  return {
386
386
  deleted: expired.length,
@@ -390,7 +390,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
390
390
  async start(input, context) {
391
391
  const email = normalizeEmail(input.email);
392
392
  if (await this.userLookup.hasActiveUser(email)) {
393
- this.logger.log(`register/start fuer aktiven Account ignoriert (${email}).`);
393
+ this.logger.log(`register/start ignored for an active account (${email}).`);
394
394
  await this.record("REGISTRATION_NEUTRAL_ACTIVE_USER", null, context);
395
395
  return {
396
396
  neutral: true
@@ -457,7 +457,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
457
457
  reason: "unknown_email"
458
458
  });
459
459
  throw new BadRequestException({
460
- code: "OTP_INVALID"
460
+ code: REGISTRATION_ERROR_CODES.OTP_INVALID
461
461
  });
462
462
  }
463
463
  if (pending.status !== "PENDING_EMAIL_VERIFICATION") {
@@ -472,7 +472,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
472
472
  reason: "no_otp_set"
473
473
  });
474
474
  throw new BadRequestException({
475
- code: "OTP_INVALID"
475
+ code: REGISTRATION_ERROR_CODES.OTP_INVALID
476
476
  });
477
477
  }
478
478
  if (pending.otpExpiresAt.getTime() < Date.now()) {
@@ -480,7 +480,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
480
480
  reason: "expired"
481
481
  });
482
482
  throw new BadRequestException({
483
- code: "OTP_EXPIRED"
483
+ code: REGISTRATION_ERROR_CODES.OTP_EXPIRED
484
484
  });
485
485
  }
486
486
  const maxAttempts = resolveOtpVerifyMaxAttempts();
@@ -489,7 +489,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
489
489
  reason: "locked"
490
490
  });
491
491
  throw new BadRequestException({
492
- code: "OTP_LOCKED"
492
+ code: REGISTRATION_ERROR_CODES.OTP_LOCKED
493
493
  });
494
494
  }
495
495
  const attemptCount = await this.repo.incrementOtpAttemptCount(pending.id);
@@ -498,7 +498,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
498
498
  reason: "locked"
499
499
  });
500
500
  throw new BadRequestException({
501
- code: "OTP_LOCKED"
501
+ code: REGISTRATION_ERROR_CODES.OTP_LOCKED
502
502
  });
503
503
  }
504
504
  if (!verifyOtpCode(pending.otpHash, code)) {
@@ -506,7 +506,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
506
506
  reason: "wrong_code"
507
507
  });
508
508
  throw new BadRequestException({
509
- code: "OTP_INVALID"
509
+ code: REGISTRATION_ERROR_CODES.OTP_INVALID
510
510
  });
511
511
  }
512
512
  const now = /* @__PURE__ */ new Date();
@@ -549,7 +549,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
549
549
  const windowMs = OTP_RATE_LIMIT_WINDOW_MINUTES * 60 * 1e3;
550
550
  const withinWindow = pending.lastOtpSentAt !== null && now.getTime() - pending.lastOtpSentAt.getTime() < windowMs;
551
551
  if (withinWindow && pending.otpSendCount >= OTP_RATE_LIMIT_MAX_SENDS) {
552
- this.logger.warn(`OTP-Rate-Limit erreicht fuer ${pending.email} \u2014 Send wird still verworfen.`);
552
+ this.logger.warn(`OTP rate limit reached for ${pending.email} \u2014 send is being skipped.`);
553
553
  return;
554
554
  }
555
555
  const code = generateOtpCode();
@@ -577,7 +577,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
577
577
  });
578
578
  } catch (error) {
579
579
  const message = error instanceof Error ? error.message : String(error);
580
- this.logger.error(`OTP-Mail an ${pending.email} fehlgeschlagen: ${message}`);
580
+ this.logger.error(`OTP email to ${pending.email} failed: ${message}`);
581
581
  }
582
582
  }
583
583
  /**
@@ -604,7 +604,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
604
604
  });
605
605
  } catch (error) {
606
606
  const message = error instanceof Error ? error.message : String(error);
607
- this.logger.error(`Resume-Mail an ${pending.email} fehlgeschlagen: ${message}`);
607
+ this.logger.error(`Resume email to ${pending.email} failed: ${message}`);
608
608
  }
609
609
  }
610
610
  /**
@@ -619,7 +619,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
619
619
  async resumeWithToken(input, context) {
620
620
  if (!this.resumeTokenSigner) {
621
621
  throw new BadRequestException({
622
- code: "RESUME_NOT_CONFIGURED"
622
+ code: REGISTRATION_ERROR_CODES.RESUME_NOT_CONFIGURED
623
623
  });
624
624
  }
625
625
  let decoded;
@@ -627,18 +627,18 @@ var PendingRegistrationService = class _PendingRegistrationService {
627
627
  decoded = await this.resumeTokenSigner.verify(input.token);
628
628
  } catch {
629
629
  throw new BadRequestException({
630
- code: "RESUME_TOKEN_INVALID"
630
+ code: REGISTRATION_ERROR_CODES.RESUME_TOKEN_INVALID
631
631
  });
632
632
  }
633
633
  const pending = await this.repo.findById(decoded.pendingRegistrationId);
634
634
  if (!pending) {
635
635
  throw new BadRequestException({
636
- code: "RESUME_TOKEN_INVALID"
636
+ code: REGISTRATION_ERROR_CODES.RESUME_TOKEN_INVALID
637
637
  });
638
638
  }
639
639
  if (pending.expiresAt.getTime() < Date.now()) {
640
640
  throw new BadRequestException({
641
- code: "PENDING_REGISTRATION_EXPIRED"
641
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_EXPIRED
642
642
  });
643
643
  }
644
644
  await this.record("REGISTRATION_NEUTRAL_REPLAY", pending.id, context, {
@@ -668,7 +668,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
668
668
  async getConfiguratorCatalog() {
669
669
  if (!this.configuratorLookup) {
670
670
  throw new BadRequestException({
671
- code: "CONFIGURATOR_NOT_CONFIGURED"
671
+ code: REGISTRATION_ERROR_CODES.CONFIGURATOR_NOT_CONFIGURED
672
672
  });
673
673
  }
674
674
  return this.configuratorLookup.getCatalog();
@@ -687,30 +687,30 @@ var PendingRegistrationService = class _PendingRegistrationService {
687
687
  async saveConfiguration(input, context) {
688
688
  if (!this.configuratorLookup) {
689
689
  throw new BadRequestException({
690
- code: "CONFIGURATOR_NOT_CONFIGURED"
690
+ code: REGISTRATION_ERROR_CODES.CONFIGURATOR_NOT_CONFIGURED
691
691
  });
692
692
  }
693
693
  const pending = await this.repo.findById(input.pendingRegistrationId);
694
694
  if (!pending) {
695
695
  throw new NotFoundException({
696
- code: "PENDING_REGISTRATION_NOT_FOUND"
696
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_NOT_FOUND
697
697
  });
698
698
  }
699
699
  if (pending.expiresAt.getTime() < Date.now()) {
700
700
  throw new BadRequestException({
701
- code: "PENDING_REGISTRATION_EXPIRED"
701
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_EXPIRED
702
702
  });
703
703
  }
704
704
  if (pending.status !== "EMAIL_VERIFIED" && pending.status !== "PLAN_SELECTED" && pending.status !== "CHECKOUT_STARTED") {
705
705
  throw new BadRequestException({
706
- code: "INVALID_REGISTRATION_STATE"
706
+ code: REGISTRATION_ERROR_CODES.INVALID_REGISTRATION_STATE
707
707
  });
708
708
  }
709
709
  const catalog = await this.configuratorLookup.getCatalog();
710
710
  const model = catalog.models.find((m) => m.id === input.selection.modelId);
711
711
  if (!model) {
712
712
  throw new BadRequestException({
713
- code: "MODEL_NOT_AVAILABLE"
713
+ code: REGISTRATION_ERROR_CODES.MODEL_NOT_AVAILABLE
714
714
  });
715
715
  }
716
716
  let promoEval;
@@ -776,26 +776,26 @@ var PendingRegistrationService = class _PendingRegistrationService {
776
776
  async previewConfigPromo(pendingRegistrationId, code) {
777
777
  if (!this.configuratorLookup) {
778
778
  throw new BadRequestException({
779
- code: "CONFIGURATOR_NOT_CONFIGURED"
779
+ code: REGISTRATION_ERROR_CODES.CONFIGURATOR_NOT_CONFIGURED
780
780
  });
781
781
  }
782
782
  const pending = await this.repo.findById(pendingRegistrationId);
783
783
  if (!pending) {
784
784
  throw new NotFoundException({
785
- code: "PENDING_REGISTRATION_NOT_FOUND"
785
+ code: REGISTRATION_ERROR_CODES.PENDING_REGISTRATION_NOT_FOUND
786
786
  });
787
787
  }
788
788
  const config = pending.configJson;
789
789
  if (!config) {
790
790
  throw new BadRequestException({
791
- code: "CONFIG_NOT_SAVED"
791
+ code: REGISTRATION_ERROR_CODES.CONFIG_NOT_SAVED
792
792
  });
793
793
  }
794
794
  const catalog = await this.configuratorLookup.getCatalog();
795
795
  const model = catalog.models.find((m) => m.id === config.modelId);
796
796
  if (!model) {
797
797
  throw new BadRequestException({
798
- code: "MODEL_NOT_AVAILABLE"
798
+ code: REGISTRATION_ERROR_CODES.MODEL_NOT_AVAILABLE
799
799
  });
800
800
  }
801
801
  let promoEval;
@@ -854,7 +854,7 @@ var PendingRegistrationService = class _PendingRegistrationService {
854
854
  return candidate;
855
855
  }
856
856
  }
857
- throw new Error(`Konnte keinen freien Slug fuer "${tenantName}" finden.`);
857
+ throw new Error(`Could not find a free slug for "${tenantName}".`);
858
858
  }
859
859
  };
860
860
  PendingRegistrationService = _ts_decorate([
@@ -979,7 +979,7 @@ var RegistrationCleanupCron = class _RegistrationCleanupCron {
979
979
  }
980
980
  }
981
981
  if (totalDeleted > 0) {
982
- this.logger.log(`PendingRegistration-Cleanup abgeschlossen: ${totalDeleted} geloescht in ${iterations} Batches.`);
982
+ this.logger.log(`Pending registration cleanup finished: ${totalDeleted} deleted in ${iterations} batches.`);
983
983
  }
984
984
  }
985
985
  };
@@ -1001,6 +1001,7 @@ RegistrationCleanupCron = _ts_decorate2([
1001
1001
 
1002
1002
  // src/registration/ip-rate-limit.guard.ts
1003
1003
  import { HttpException, HttpStatus, Injectable as Injectable3 } from "@nestjs/common";
1004
+ import { REGISTRATION_ERROR_CODES as REGISTRATION_ERROR_CODES2 } from "@saasicat/types";
1004
1005
  function _ts_decorate3(decorators, target, key, desc) {
1005
1006
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1006
1007
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1029,7 +1030,7 @@ var BaseIpRateLimitGuard = class {
1029
1030
  const key = ipFingerprint(req);
1030
1031
  if (this.exceeded(key)) {
1031
1032
  throw new HttpException({
1032
- code: "RATE_LIMITED",
1033
+ code: REGISTRATION_ERROR_CODES2.RATE_LIMITED,
1033
1034
  reason: this.options.name,
1034
1035
  retryAfterSeconds: Math.ceil(this.options.windowMs / 1e3)
1035
1036
  }, HttpStatus.TOO_MANY_REQUESTS);
@@ -1173,7 +1174,7 @@ _ts_decorate5([
1173
1174
  IsOptional(),
1174
1175
  IsString(),
1175
1176
  Matches(/^[a-z0-9-]+$/, {
1176
- message: "tenantSlug darf nur Kleinbuchstaben, Ziffern und Bindestriche enthalten."
1177
+ message: "tenantSlug may only contain lower-case letters, digits and hyphens."
1177
1178
  }),
1178
1179
  MaxLength(60),
1179
1180
  _ts_metadata4("design:type", String)
@@ -1209,7 +1210,7 @@ _ts_decorate5([
1209
1210
  ], RegisterStartDto.prototype, "password", void 0);
1210
1211
  _ts_decorate5([
1211
1212
  Equals(true, {
1212
- message: "AGB, Datenschutzerklaerung und Auftragsverarbeitung muessen zugestimmt werden."
1213
+ message: "The terms of service, privacy policy and data processing agreement must be accepted."
1213
1214
  }),
1214
1215
  _ts_metadata4("design:type", Boolean)
1215
1216
  ], RegisterStartDto.prototype, "termsAccepted", void 0);
@@ -1249,7 +1250,7 @@ _ts_decorate6([
1249
1250
  _ts_decorate6([
1250
1251
  IsString2(),
1251
1252
  Matches2(/^\d{6}$/, {
1252
- message: "OTP muss 6 Ziffern sein."
1253
+ message: "The OTP must be 6 digits."
1253
1254
  }),
1254
1255
  _ts_metadata5("design:type", String)
1255
1256
  ], VerifyRegistrationOtpDto.prototype, "otp", void 0);
@@ -2,7 +2,7 @@ import {
2
2
  DISCOVERY_APP_INFO_TOKEN,
3
3
  DISCOVERY_SNAPSHOT_PATH_TOKEN,
4
4
  DiscoveryScanner
5
- } from "./chunk-Z3FWN3HJ.js";
5
+ } from "./chunk-5ZXBXYXU.js";
6
6
  import {
7
7
  DISCOVERY_SNAPSHOT_TOKEN
8
8
  } from "./chunk-L4SUWH5B.js";
@@ -11,7 +11,7 @@ var DiscoverySnapshotNotFoundError = class extends Error {
11
11
  }
12
12
  path;
13
13
  constructor(path) {
14
- super(`Discovery-Snapshot-Datei nicht gefunden: ${path}. Booten Sie zuerst die App mit DISCOVERY_SNAPSHOT_PATH oder DiscoveryModule.forRoot({ snapshotPath: '\u2026' }), damit der Scanner die Datei beim OnApplicationBootstrap-Hook schreibt.`), this.path = path;
14
+ super(`Discovery snapshot file not found: ${path}. Boot the app first with DISCOVERY_SNAPSHOT_PATH or DiscoveryModule.forRoot({ snapshotPath: '\u2026' }) so that the scanner writes the file on the OnApplicationBootstrap hook.`), this.path = path;
15
15
  this.name = "DiscoverySnapshotNotFoundError";
16
16
  }
17
17
  };