@saasicat/nest 0.2.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 (96) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +53 -0
  3. package/dist/admin/index.cjs +1283 -0
  4. package/dist/admin/index.d.cts +225 -0
  5. package/dist/admin/index.d.ts +225 -0
  6. package/dist/admin/index.js +58 -0
  7. package/dist/admin-audit.service-9IqXMlZm.d.cts +30 -0
  8. package/dist/admin-audit.service-9IqXMlZm.d.ts +30 -0
  9. package/dist/admin-manifest.config-DyrQNT7M.d.cts +10 -0
  10. package/dist/admin-manifest.config-DyrQNT7M.d.ts +10 -0
  11. package/dist/aggregation-CJ3qQf92.d.cts +288 -0
  12. package/dist/aggregation-Dvz9e8X2.d.ts +288 -0
  13. package/dist/billing/index.cjs +5205 -0
  14. package/dist/billing/index.d.cts +1326 -0
  15. package/dist/billing/index.d.ts +1326 -0
  16. package/dist/billing/index.js +197 -0
  17. package/dist/catalog/index.cjs +6449 -0
  18. package/dist/catalog/index.d.cts +1073 -0
  19. package/dist/catalog/index.d.ts +1073 -0
  20. package/dist/catalog/index.js +158 -0
  21. package/dist/checkout-offer/index.cjs +807 -0
  22. package/dist/checkout-offer/index.d.cts +120 -0
  23. package/dist/checkout-offer/index.d.ts +120 -0
  24. package/dist/checkout-offer/index.js +20 -0
  25. package/dist/chunk-2FR6ZL7R.js +0 -0
  26. package/dist/chunk-2PNX2QL2.js +347 -0
  27. package/dist/chunk-2VNZYRDV.js +326 -0
  28. package/dist/chunk-7MLGHWKO.js +12 -0
  29. package/dist/chunk-ABB2CRAS.js +31 -0
  30. package/dist/chunk-AJ3EPELS.js +157 -0
  31. package/dist/chunk-E56W4U2P.js +90 -0
  32. package/dist/chunk-HRU3CP57.js +71 -0
  33. package/dist/chunk-L4SUWH5B.js +14 -0
  34. package/dist/chunk-M6CZQYPY.js +314 -0
  35. package/dist/chunk-MDIZUVIK.js +87 -0
  36. package/dist/chunk-MV6LW5UB.js +217 -0
  37. package/dist/chunk-NYLON2VC.js +6 -0
  38. package/dist/chunk-P6MYZMXQ.js +951 -0
  39. package/dist/chunk-Q53N43LQ.js +13 -0
  40. package/dist/chunk-QJVPRD3R.js +573 -0
  41. package/dist/chunk-RIGLQ4BV.js +3367 -0
  42. package/dist/chunk-SABTXESR.js +24 -0
  43. package/dist/chunk-SHUYVCID.js +6 -0
  44. package/dist/chunk-SYEVGPFC.js +686 -0
  45. package/dist/chunk-V7HUZ6UQ.js +5923 -0
  46. package/dist/chunk-WPUVJRIN.js +29 -0
  47. package/dist/chunk-XCZ3TTFK.js +22 -0
  48. package/dist/chunk-XSGU2Y2O.js +1611 -0
  49. package/dist/chunk-YNEW3L63.js +190 -0
  50. package/dist/chunk-YXGHPILG.js +614 -0
  51. package/dist/chunk-ZL4LLE2Z.js +465 -0
  52. package/dist/di-CcNeq9v-.d.cts +16 -0
  53. package/dist/di-CcNeq9v-.d.ts +16 -0
  54. package/dist/discovery/index.cjs +588 -0
  55. package/dist/discovery/index.d.cts +299 -0
  56. package/dist/discovery/index.d.ts +299 -0
  57. package/dist/discovery/index.js +49 -0
  58. package/dist/discovery.scanner-CUYLKlYT.d.cts +59 -0
  59. package/dist/discovery.scanner-CUYLKlYT.d.ts +59 -0
  60. package/dist/entitlement/index.cjs +805 -0
  61. package/dist/entitlement/index.d.cts +60 -0
  62. package/dist/entitlement/index.d.ts +60 -0
  63. package/dist/entitlement/index.js +57 -0
  64. package/dist/index.cjs +15918 -0
  65. package/dist/index.d.cts +85 -0
  66. package/dist/index.d.ts +85 -0
  67. package/dist/index.js +956 -0
  68. package/dist/plan-resolution-CFCoUkrE.d.cts +41 -0
  69. package/dist/plan-resolution-CFCoUkrE.d.ts +41 -0
  70. package/dist/platform/index.cjs +2772 -0
  71. package/dist/platform/index.d.cts +118 -0
  72. package/dist/platform/index.d.ts +118 -0
  73. package/dist/platform/index.js +37 -0
  74. package/dist/promo/index.cjs +995 -0
  75. package/dist/promo/index.d.cts +121 -0
  76. package/dist/promo/index.d.ts +121 -0
  77. package/dist/promo/index.js +58 -0
  78. package/dist/registration/index.cjs +1687 -0
  79. package/dist/registration/index.d.cts +444 -0
  80. package/dist/registration/index.d.ts +444 -0
  81. package/dist/registration/index.js +82 -0
  82. package/dist/saas-platform.module-CgZ2omgg.d.cts +180 -0
  83. package/dist/saas-platform.module-DT9TnCzk.d.ts +180 -0
  84. package/dist/service-DX8KbGXl.d.cts +109 -0
  85. package/dist/service-DX8KbGXl.d.ts +109 -0
  86. package/dist/subscription-contract/index.cjs +471 -0
  87. package/dist/subscription-contract/index.d.cts +17 -0
  88. package/dist/subscription-contract/index.d.ts +17 -0
  89. package/dist/subscription-contract/index.js +21 -0
  90. package/dist/subscription-contract.service--cm47ZJJ.d.cts +39 -0
  91. package/dist/subscription-contract.service--cm47ZJJ.d.ts +39 -0
  92. package/dist/testing/index.cjs +3942 -0
  93. package/dist/testing/index.d.cts +279 -0
  94. package/dist/testing/index.d.ts +279 -0
  95. package/dist/testing/index.js +1195 -0
  96. package/package.json +185 -0
@@ -0,0 +1,951 @@
1
+ import {
2
+ AUDIT_PORT_TOKEN,
3
+ AdminAuditService,
4
+ MFA_PORT_TOKEN,
5
+ RLS_BYPASS_PORT_TOKEN
6
+ } from "./chunk-E56W4U2P.js";
7
+ import {
8
+ asProvider
9
+ } from "./chunk-SABTXESR.js";
10
+ import {
11
+ __name
12
+ } from "./chunk-SHUYVCID.js";
13
+
14
+ // src/admin/super-admin.guard.ts
15
+ import { ForbiddenException, Injectable } from "@nestjs/common";
16
+ function _ts_decorate(decorators, target, key, desc) {
17
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ }
22
+ __name(_ts_decorate, "_ts_decorate");
23
+ var SuperAdminGuard = class {
24
+ static {
25
+ __name(this, "SuperAdminGuard");
26
+ }
27
+ canActivate(context) {
28
+ const request = context.switchToHttp().getRequest();
29
+ if (!request.user) throw new ForbiddenException("Nicht authentifiziert");
30
+ if (request.user.role !== "SUPER_ADMIN") {
31
+ throw new ForbiddenException("Nur SUPER_ADMIN-Rolle erlaubt");
32
+ }
33
+ return true;
34
+ }
35
+ };
36
+ SuperAdminGuard = _ts_decorate([
37
+ Injectable()
38
+ ], SuperAdminGuard);
39
+
40
+ // src/admin/mfa.ts
41
+ import { Inject, Injectable as Injectable2, Logger } from "@nestjs/common";
42
+ import { generateSecret, generateURI, verify as verifyTotpCode } from "otplib";
43
+ function _ts_decorate2(decorators, target, key, desc) {
44
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
45
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
46
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
47
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
48
+ }
49
+ __name(_ts_decorate2, "_ts_decorate");
50
+ function _ts_metadata(k, v) {
51
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
52
+ }
53
+ __name(_ts_metadata, "_ts_metadata");
54
+ function _ts_param(paramIndex, decorator) {
55
+ return function(target, key) {
56
+ decorator(target, key, paramIndex);
57
+ };
58
+ }
59
+ __name(_ts_param, "_ts_param");
60
+ var CLOCK_DRIFT_TOLERANCE_SECONDS = 30;
61
+ var OTPLIB_TOKEN_ERROR_NAMES = /* @__PURE__ */ new Set([
62
+ "TokenError",
63
+ "TokenFormatError",
64
+ "TokenLengthError"
65
+ ]);
66
+ function isOtplibTokenError(error) {
67
+ return error instanceof Error && OTPLIB_TOKEN_ERROR_NAMES.has(error.name);
68
+ }
69
+ __name(isOtplibTokenError, "isOtplibTokenError");
70
+ var MfaService = class _MfaService {
71
+ static {
72
+ __name(this, "MfaService");
73
+ }
74
+ mfa;
75
+ logger = new Logger(_MfaService.name);
76
+ constructor(mfa) {
77
+ this.mfa = mfa;
78
+ }
79
+ /**
80
+ * Generates a new TOTP secret, persists it via `MfaPort.setSecret`
81
+ * and returns the secret + the otpauth URI for the QR code.
82
+ *
83
+ * `issuer` and `label` shape the display in the authenticator (e.g.
84
+ * "DemoApp:taci@example.com").
85
+ */
86
+ async setup(userId, label, issuer) {
87
+ const secret = generateSecret();
88
+ const otpauthUri = generateURI({
89
+ issuer,
90
+ label,
91
+ secret
92
+ });
93
+ await this.mfa.setSecret(userId, secret);
94
+ return {
95
+ secret,
96
+ otpauthUri
97
+ };
98
+ }
99
+ /**
100
+ * Verifies the entered code against the stored secret,
101
+ * clock-drift-tolerant by ±1 time step.
102
+ */
103
+ async verify(input) {
104
+ const secret = await this.mfa.getSecret(input.userId);
105
+ if (!secret) return false;
106
+ try {
107
+ const result = await verifyTotpCode({
108
+ secret,
109
+ token: input.code.trim(),
110
+ epochTolerance: CLOCK_DRIFT_TOLERANCE_SECONDS
111
+ });
112
+ return result.valid;
113
+ } catch (error) {
114
+ if (isOtplibTokenError(error)) {
115
+ return false;
116
+ }
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ this.logger.warn(`TOTP-Verify f\xFCr User ${input.userId} unerwartet fehlgeschlagen: ${message}`);
119
+ return false;
120
+ }
121
+ }
122
+ /**
123
+ * Deletes a user's secret — used by `ahp admin mfa-reset`.
124
+ */
125
+ async disable(userId) {
126
+ await this.mfa.setSecret(userId, null);
127
+ }
128
+ /** Delegates to `MfaPort.isEnabled`. */
129
+ async isEnabled(userId) {
130
+ return this.mfa.isEnabled(userId);
131
+ }
132
+ };
133
+ MfaService = _ts_decorate2([
134
+ Injectable2(),
135
+ _ts_param(0, Inject(MFA_PORT_TOKEN)),
136
+ _ts_metadata("design:type", Function),
137
+ _ts_metadata("design:paramtypes", [
138
+ typeof MfaPort === "undefined" ? Object : MfaPort
139
+ ])
140
+ ], MfaService);
141
+
142
+ // src/admin/mfa.guard.ts
143
+ import { Inject as Inject2, Injectable as Injectable3, Logger as Logger2, SetMetadata, UnauthorizedException } from "@nestjs/common";
144
+ import { Reflector } from "@nestjs/core";
145
+ function _ts_decorate3(decorators, target, key, desc) {
146
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
147
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
148
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
149
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
150
+ }
151
+ __name(_ts_decorate3, "_ts_decorate");
152
+ function _ts_metadata2(k, v) {
153
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
154
+ }
155
+ __name(_ts_metadata2, "_ts_metadata");
156
+ function _ts_param2(paramIndex, decorator) {
157
+ return function(target, key) {
158
+ decorator(target, key, paramIndex);
159
+ };
160
+ }
161
+ __name(_ts_param2, "_ts_param");
162
+ var REQUIRE_MFA_KEY = "saas-platform/require-mfa";
163
+ var RequireMfa = /* @__PURE__ */ __name(() => SetMetadata(REQUIRE_MFA_KEY, true), "RequireMfa");
164
+ var MfaGuard = class _MfaGuard {
165
+ static {
166
+ __name(this, "MfaGuard");
167
+ }
168
+ reflector;
169
+ mfaService;
170
+ logger = new Logger2(_MfaGuard.name);
171
+ constructor(reflector, mfaService) {
172
+ this.reflector = reflector;
173
+ this.mfaService = mfaService;
174
+ }
175
+ async canActivate(context) {
176
+ const required = this.reflector.getAllAndOverride(REQUIRE_MFA_KEY, [
177
+ context.getHandler(),
178
+ context.getClass()
179
+ ]);
180
+ if (!required) return true;
181
+ if (process.env.SAAS_PLATFORM_SKIP_MFA === "1" && process.env.NODE_ENV !== "production") {
182
+ return true;
183
+ }
184
+ const request = context.switchToHttp().getRequest();
185
+ const user = request.user;
186
+ if (!user) throw new UnauthorizedException({
187
+ reason: "NOT_AUTHENTICATED"
188
+ });
189
+ const enabled = await this.mfaService.isEnabled(user.id);
190
+ if (!enabled) {
191
+ throw new UnauthorizedException({
192
+ reason: "MFA_NOT_SET_UP",
193
+ message: "Bitte zuerst MFA-Setup \xFCber das CLI ausf\xFChren."
194
+ });
195
+ }
196
+ const headerVal = request.headers?.["x-mfa-code"];
197
+ const code = Array.isArray(headerVal) ? headerVal[0] : headerVal;
198
+ if (!code) {
199
+ throw new UnauthorizedException({
200
+ reason: "MFA_REQUIRED",
201
+ message: "TOTP-Code im Header X-Mfa-Code erforderlich."
202
+ });
203
+ }
204
+ const valid = await this.mfaService.verify({
205
+ userId: user.id,
206
+ code: String(code)
207
+ });
208
+ if (!valid) {
209
+ throw new UnauthorizedException({
210
+ reason: "MFA_FAILED",
211
+ message: "TOTP-Code ung\xFCltig."
212
+ });
213
+ }
214
+ return true;
215
+ }
216
+ };
217
+ MfaGuard = _ts_decorate3([
218
+ Injectable3(),
219
+ _ts_param2(0, Inject2(Reflector)),
220
+ _ts_metadata2("design:type", Function),
221
+ _ts_metadata2("design:paramtypes", [
222
+ typeof Reflector === "undefined" ? Object : Reflector,
223
+ typeof MfaService === "undefined" ? Object : MfaService
224
+ ])
225
+ ], MfaGuard);
226
+
227
+ // src/admin/admin-bypass-rls.interceptor.ts
228
+ import { Inject as Inject3, Injectable as Injectable4 } from "@nestjs/common";
229
+ import { defer, from } from "rxjs";
230
+ import { switchAll } from "rxjs/operators";
231
+ function _ts_decorate4(decorators, target, key, desc) {
232
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
233
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
234
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
235
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
236
+ }
237
+ __name(_ts_decorate4, "_ts_decorate");
238
+ function _ts_metadata3(k, v) {
239
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
240
+ }
241
+ __name(_ts_metadata3, "_ts_metadata");
242
+ function _ts_param3(paramIndex, decorator) {
243
+ return function(target, key) {
244
+ decorator(target, key, paramIndex);
245
+ };
246
+ }
247
+ __name(_ts_param3, "_ts_param");
248
+ var AdminBypassRlsInterceptor = class {
249
+ static {
250
+ __name(this, "AdminBypassRlsInterceptor");
251
+ }
252
+ port;
253
+ constructor(port) {
254
+ this.port = port;
255
+ }
256
+ intercept(_context, next) {
257
+ return defer(() => from(this.port.runWithBypass(async () => {
258
+ return next.handle();
259
+ })).pipe(switchAll()));
260
+ }
261
+ };
262
+ AdminBypassRlsInterceptor = _ts_decorate4([
263
+ Injectable4(),
264
+ _ts_param3(0, Inject3(RLS_BYPASS_PORT_TOKEN)),
265
+ _ts_metadata3("design:type", Function),
266
+ _ts_metadata3("design:paramtypes", [
267
+ typeof RlsBypassPort === "undefined" ? Object : RlsBypassPort
268
+ ])
269
+ ], AdminBypassRlsInterceptor);
270
+
271
+ // src/admin/module.ts
272
+ import { Module } from "@nestjs/common";
273
+ function _ts_decorate5(decorators, target, key, desc) {
274
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
275
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
276
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
277
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
278
+ }
279
+ __name(_ts_decorate5, "_ts_decorate");
280
+ var AdminModule = class _AdminModule {
281
+ static {
282
+ __name(this, "AdminModule");
283
+ }
284
+ static forRoot(options) {
285
+ const providers = [
286
+ asProvider(MFA_PORT_TOKEN, options.mfaPort),
287
+ asProvider(AUDIT_PORT_TOKEN, options.auditPort),
288
+ asProvider(RLS_BYPASS_PORT_TOKEN, options.rlsBypassPort),
289
+ MfaService,
290
+ AdminAuditService,
291
+ SuperAdminGuard,
292
+ MfaGuard,
293
+ AdminBypassRlsInterceptor
294
+ ];
295
+ return {
296
+ module: _AdminModule,
297
+ global: options.global ?? false,
298
+ providers,
299
+ exports: [
300
+ MFA_PORT_TOKEN,
301
+ AUDIT_PORT_TOKEN,
302
+ RLS_BYPASS_PORT_TOKEN,
303
+ MfaService,
304
+ AdminAuditService,
305
+ SuperAdminGuard,
306
+ MfaGuard,
307
+ AdminBypassRlsInterceptor
308
+ ]
309
+ };
310
+ }
311
+ };
312
+ AdminModule = _ts_decorate5([
313
+ Module({})
314
+ ], AdminModule);
315
+
316
+ // src/admin/admin-manifest.config.ts
317
+ var ADMIN_MANIFEST_CONFIG = /* @__PURE__ */ Symbol("ADMIN_MANIFEST_CONFIG");
318
+
319
+ // src/admin/admin-manifest.service.ts
320
+ import { Inject as Inject4, Injectable as Injectable5, Logger as Logger3, Optional } from "@nestjs/common";
321
+ import { createHash } from "crypto";
322
+ function _ts_decorate6(decorators, target, key, desc) {
323
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
324
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
325
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
326
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
327
+ }
328
+ __name(_ts_decorate6, "_ts_decorate");
329
+ function _ts_metadata4(k, v) {
330
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
331
+ }
332
+ __name(_ts_metadata4, "_ts_metadata");
333
+ function _ts_param4(paramIndex, decorator) {
334
+ return function(target, key) {
335
+ decorator(target, key, paramIndex);
336
+ };
337
+ }
338
+ __name(_ts_param4, "_ts_param");
339
+ var PLATFORM_CORE_CONTRIBUTION_TOKEN = /* @__PURE__ */ Symbol("PLATFORM_CORE_CONTRIBUTION");
340
+ var AdminManifestService = class _AdminManifestService {
341
+ static {
342
+ __name(this, "AdminManifestService");
343
+ }
344
+ config;
345
+ logger = new Logger3(_AdminManifestService.name);
346
+ contributions = [];
347
+ cached = null;
348
+ constructor(config, platformCore = null) {
349
+ this.config = config;
350
+ if (platformCore) {
351
+ this.contributions.push(platformCore);
352
+ }
353
+ }
354
+ register(contribution) {
355
+ this.contributions.push(contribution);
356
+ this.cached = null;
357
+ }
358
+ getManifest() {
359
+ if (this.cached) return this.cached;
360
+ this.cached = this.build();
361
+ this.logger.log(`Manifest built: ${this.contributions.length} contribution(s), hash=${this.cached.build.manifestHash.slice(0, 24)}\u2026`);
362
+ return this.cached;
363
+ }
364
+ rebuild() {
365
+ this.cached = null;
366
+ return this.getManifest();
367
+ }
368
+ build() {
369
+ const merged = this.mergeContributions(this.contributions);
370
+ const draft = {
371
+ schemaVersion: 1,
372
+ project: this.config.project,
373
+ build: {
374
+ ...this.config.build,
375
+ manifestHash: "sha256-pending"
376
+ },
377
+ planCatalogSnapshot: this.config.planCatalogSnapshot,
378
+ capabilities: merged.capabilities,
379
+ navigation: merged.navigation,
380
+ dashboard: merged.dashboard,
381
+ tenants: merged.tenants,
382
+ audit: merged.audit
383
+ };
384
+ return {
385
+ ...draft,
386
+ build: {
387
+ ...draft.build,
388
+ manifestHash: this.computeHash(draft)
389
+ }
390
+ };
391
+ }
392
+ mergeContributions(contributions) {
393
+ const capabilities = {};
394
+ const standardPages = {};
395
+ const projectPages = [];
396
+ const kpiCards = [];
397
+ const tenantColumns = [];
398
+ const tenantActions = [];
399
+ const auditActions = [];
400
+ for (const c of contributions) {
401
+ if (c.capabilities) Object.assign(capabilities, c.capabilities);
402
+ if (c.navigation?.standardPages) Object.assign(standardPages, c.navigation.standardPages);
403
+ if (c.navigation?.projectPages) projectPages.push(...c.navigation.projectPages);
404
+ if (c.dashboard?.kpiCards) kpiCards.push(...c.dashboard.kpiCards);
405
+ if (c.tenants?.columns) tenantColumns.push(...c.tenants.columns);
406
+ if (c.tenants?.actions) tenantActions.push(...c.tenants.actions);
407
+ if (c.audit?.actions) auditActions.push(...c.audit.actions);
408
+ }
409
+ kpiCards.sort((a, b) => (b.slotPriority ?? 0) - (a.slotPriority ?? 0));
410
+ return {
411
+ capabilities,
412
+ navigation: {
413
+ standardPages,
414
+ projectPages
415
+ },
416
+ dashboard: kpiCards.length > 0 ? {
417
+ kpiCards
418
+ } : void 0,
419
+ tenants: tenantColumns.length > 0 || tenantActions.length > 0 ? {
420
+ columns: tenantColumns,
421
+ actions: tenantActions
422
+ } : void 0,
423
+ audit: auditActions.length > 0 ? {
424
+ actions: auditActions
425
+ } : void 0
426
+ };
427
+ }
428
+ /**
429
+ * Deterministic SHA-256 hash over the manifest. Uses the insertion
430
+ * order of the object keys — so that semantically meaningful reorders (e.g.
431
+ * the order of the sidebar items in `navigation.standardPages`) change the
432
+ * hash and invalidate the browser ETag cache. The manifest's own
433
+ * `manifestHash` field is hidden before serialization.
434
+ */
435
+ computeHash(manifest) {
436
+ const canonical = stableStringify({
437
+ ...manifest,
438
+ build: {
439
+ ...manifest.build,
440
+ manifestHash: void 0
441
+ }
442
+ });
443
+ const digest = createHash("sha256").update(canonical).digest("base64url");
444
+ return `sha256-${digest}`;
445
+ }
446
+ };
447
+ AdminManifestService = _ts_decorate6([
448
+ Injectable5(),
449
+ _ts_param4(0, Inject4(ADMIN_MANIFEST_CONFIG)),
450
+ _ts_param4(1, Optional()),
451
+ _ts_param4(1, Inject4(PLATFORM_CORE_CONTRIBUTION_TOKEN)),
452
+ _ts_metadata4("design:type", Function),
453
+ _ts_metadata4("design:paramtypes", [
454
+ typeof AdminManifestConfig === "undefined" ? Object : AdminManifestConfig,
455
+ Object
456
+ ])
457
+ ], AdminManifestService);
458
+ function stableStringify(value) {
459
+ if (value === null) return "null";
460
+ if (value === void 0) return "null";
461
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "null";
462
+ if (typeof value === "boolean") return value ? "true" : "false";
463
+ if (typeof value === "string") return JSON.stringify(value);
464
+ if (Array.isArray(value)) {
465
+ return "[" + value.map(stableStringify).join(",") + "]";
466
+ }
467
+ if (typeof value === "object") {
468
+ const obj = value;
469
+ const keys = Object.keys(obj).filter((k) => obj[k] !== void 0);
470
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
471
+ }
472
+ return JSON.stringify(value);
473
+ }
474
+ __name(stableStringify, "stableStringify");
475
+
476
+ // src/admin/admin-public-boot.controller.ts
477
+ import { Controller, Get, Inject as Inject5 } from "@nestjs/common";
478
+ function _ts_decorate7(decorators, target, key, desc) {
479
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
480
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
481
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
482
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
483
+ }
484
+ __name(_ts_decorate7, "_ts_decorate");
485
+ function _ts_metadata5(k, v) {
486
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
487
+ }
488
+ __name(_ts_metadata5, "_ts_metadata");
489
+ function _ts_param5(paramIndex, decorator) {
490
+ return function(target, key) {
491
+ decorator(target, key, paramIndex);
492
+ };
493
+ }
494
+ __name(_ts_param5, "_ts_param");
495
+ var AdminPublicBootController = class {
496
+ static {
497
+ __name(this, "AdminPublicBootController");
498
+ }
499
+ config;
500
+ constructor(config) {
501
+ this.config = config;
502
+ }
503
+ getBoot() {
504
+ return {
505
+ project: {
506
+ key: this.config.project.key,
507
+ displayName: this.config.project.displayName,
508
+ label: this.config.project.label,
509
+ icon: this.config.project.icon,
510
+ logoUrl: this.config.project.logoUrl,
511
+ environment: this.config.project.environment
512
+ }
513
+ };
514
+ }
515
+ };
516
+ _ts_decorate7([
517
+ Get("boot"),
518
+ _ts_metadata5("design:type", Function),
519
+ _ts_metadata5("design:paramtypes", []),
520
+ _ts_metadata5("design:returntype", typeof PublicBootResponse === "undefined" ? Object : PublicBootResponse)
521
+ ], AdminPublicBootController.prototype, "getBoot", null);
522
+ AdminPublicBootController = _ts_decorate7([
523
+ Controller("admin"),
524
+ _ts_param5(0, Inject5(ADMIN_MANIFEST_CONFIG)),
525
+ _ts_metadata5("design:type", Function),
526
+ _ts_metadata5("design:paramtypes", [
527
+ typeof AdminManifestConfig === "undefined" ? Object : AdminManifestConfig
528
+ ])
529
+ ], AdminPublicBootController);
530
+
531
+ // src/admin/manifest-core.ts
532
+ var PLATFORM_CORE_MANIFEST_CONTRIBUTION = {
533
+ navigation: {
534
+ // Key order is render order in the sidebar (within the
535
+ // section, see `DEFAULT_NAV_SECTIONS` in the nav-builder). The order per
536
+ // section is deliberately curated:
537
+ // Overview: dashboard
538
+ // Product catalog: discovery → bundles → businessTypes → plans →
539
+ // planVersions → marketingCatalog → promoCodes
540
+ // (promoCodes is appended by the app contributions
541
+ // and therefore lands at the end of the section)
542
+ // Customers: tenants → users → pilots
543
+ // System: audit
544
+ standardPages: {
545
+ dashboard: {
546
+ enabled: true,
547
+ requiredCapability: "dashboard.read"
548
+ },
549
+ // SPEC_V2 §3.3 — discovery snapshot of the running backend.
550
+ // Apps must set `discovery.read` in their manifest capabilities
551
+ // to `true` so that the NavBuilder wires the page into the
552
+ // sidebar; otherwise it is filtered out automatically.
553
+ discovery: {
554
+ enabled: true,
555
+ requiredCapability: "discovery.read"
556
+ },
557
+ // SPEC_V2 §11.1 M3 — Bundle editor in SuperAdmin.
558
+ // Apps with a DB-driven catalog set `bundles.read = true`.
559
+ bundles: {
560
+ enabled: true,
561
+ requiredCapability: "bundles.read"
562
+ },
563
+ // SPEC_V2 §11.1 M3 — BusinessType editor in SuperAdmin.
564
+ // Apps with domain verticals set `businessTypes.read = true`.
565
+ businessTypes: {
566
+ enabled: true,
567
+ requiredCapability: "businessTypes.read"
568
+ },
569
+ plans: {
570
+ enabled: true,
571
+ requiredCapability: "plans.read"
572
+ },
573
+ planVersions: {
574
+ enabled: true,
575
+ requiredCapability: "plans.read"
576
+ },
577
+ // SPEC_V2 §11.1 M3 — marketing catalog (locale pivot).
578
+ // Apps that market a public catalog set
579
+ // `marketingProjections.read = true`.
580
+ marketingCatalog: {
581
+ enabled: true,
582
+ requiredCapability: "marketingProjections.read"
583
+ },
584
+ tenants: {
585
+ enabled: true,
586
+ requiredCapability: "tenants.read"
587
+ },
588
+ users: {
589
+ enabled: true,
590
+ requiredCapability: "users.read"
591
+ },
592
+ pilots: {
593
+ enabled: true,
594
+ requiredCapability: "pilots.read"
595
+ },
596
+ // Audit log deliberately at the end — rarely needed, should
597
+ // not obscure the productive pages.
598
+ audit: {
599
+ enabled: true,
600
+ requiredCapability: "audit.read"
601
+ },
602
+ // Platform email sender (system/registration mails). Apps
603
+ // set `platformEmail.read = true` so that the NavBuilder wires the page
604
+ // in; otherwise it is filtered out automatically.
605
+ platformEmail: {
606
+ enabled: true,
607
+ requiredCapability: "platformEmail.read"
608
+ },
609
+ // Platform email history (audit of the sent system mails). Apps
610
+ // set `platformEmailHistory.read = true` so that the NavBuilder wires the
611
+ // page in; otherwise it is filtered out automatically.
612
+ platformEmailHistory: {
613
+ enabled: true,
614
+ requiredCapability: "platformEmailHistory.read"
615
+ }
616
+ }
617
+ },
618
+ tenants: {
619
+ actions: [
620
+ {
621
+ id: "platform.tenants.suspend",
622
+ label: "Mandant suspendieren",
623
+ actionKey: "tenants.suspend",
624
+ requiredCapability: "tenants.suspend",
625
+ requiresMfa: true,
626
+ confirmType: "typed-slug"
627
+ },
628
+ {
629
+ id: "platform.tenants.reactivate",
630
+ label: "Mandant reaktivieren",
631
+ actionKey: "tenants.reactivate",
632
+ requiredCapability: "tenants.reactivate",
633
+ requiresMfa: true,
634
+ confirmType: "simple"
635
+ },
636
+ {
637
+ id: "platform.tenants.impersonate",
638
+ label: "Impersonate",
639
+ actionKey: "tenants.impersonate",
640
+ requiredCapability: "tenants.impersonate",
641
+ requiresMfa: true,
642
+ confirmType: "simple"
643
+ },
644
+ {
645
+ id: "platform.tenants.export",
646
+ label: "DSGVO-Export",
647
+ actionKey: "tenants.export",
648
+ requiredCapability: "tenants.export",
649
+ requiresMfa: true,
650
+ confirmType: "simple"
651
+ },
652
+ {
653
+ id: "platform.subscriptions.cancel",
654
+ label: "Subscription k\xFCndigen",
655
+ actionKey: "subscriptions.cancel",
656
+ requiredCapability: "subscriptions.cancel",
657
+ requiresMfa: true,
658
+ confirmType: "typed-slug"
659
+ },
660
+ {
661
+ id: "platform.pilots.grant",
662
+ label: "Pilot-Status setzen",
663
+ actionKey: "pilots.grant",
664
+ requiredCapability: "pilots.grant",
665
+ requiresMfa: true,
666
+ confirmType: "simple"
667
+ },
668
+ {
669
+ id: "platform.pilots.revoke",
670
+ label: "Pilot-Status entziehen",
671
+ actionKey: "pilots.revoke",
672
+ requiredCapability: "pilots.revoke",
673
+ requiresMfa: true,
674
+ confirmType: "typed-slug"
675
+ },
676
+ {
677
+ id: "platform.pilots.extend",
678
+ label: "Pilot verl\xE4ngern",
679
+ actionKey: "pilots.extend",
680
+ requiredCapability: "pilots.extend",
681
+ requiresMfa: true,
682
+ confirmType: "date"
683
+ }
684
+ ]
685
+ },
686
+ audit: {
687
+ actions: [
688
+ {
689
+ key: "TENANT_SUSPEND",
690
+ label: "Mandant suspendiert",
691
+ severity: "high"
692
+ },
693
+ {
694
+ key: "TENANT_REACTIVATE",
695
+ label: "Mandant reaktiviert",
696
+ severity: "medium"
697
+ },
698
+ {
699
+ key: "TENANT_IMPERSONATE",
700
+ label: "Impersonation gestartet",
701
+ severity: "high"
702
+ },
703
+ {
704
+ key: "TENANT_EXPORT",
705
+ label: "DSGVO-Export ausgel\xF6st",
706
+ severity: "medium"
707
+ },
708
+ {
709
+ key: "PILOT_CREATE",
710
+ label: "Pilot-Tenant angelegt",
711
+ severity: "medium"
712
+ },
713
+ {
714
+ key: "PILOT_GRANT",
715
+ label: "Pilot-Status gesetzt",
716
+ severity: "medium"
717
+ },
718
+ {
719
+ key: "PILOT_REVOKE",
720
+ label: "Pilot-Status entzogen",
721
+ severity: "medium"
722
+ },
723
+ {
724
+ key: "PILOT_EXTEND",
725
+ label: "Pilot verl\xE4ngert",
726
+ severity: "low"
727
+ },
728
+ {
729
+ key: "PLAN_VERSION_PUBLISH",
730
+ label: "Plan-Version freigegeben",
731
+ severity: "high"
732
+ },
733
+ {
734
+ key: "PLAN_VERSION_TERMINATE",
735
+ label: "Plan-Version terminiert",
736
+ severity: "high"
737
+ },
738
+ {
739
+ key: "SUBSCRIPTION_CANCEL",
740
+ label: "Subscription gek\xFCndigt",
741
+ severity: "high"
742
+ },
743
+ {
744
+ key: "USER_RESET_PASSWORD",
745
+ label: "Passwort-Reset ausgel\xF6st",
746
+ severity: "medium"
747
+ },
748
+ {
749
+ key: "USER_DEACTIVATE",
750
+ label: "User deaktiviert",
751
+ severity: "high"
752
+ },
753
+ {
754
+ key: "USER_REASSIGN_ADMIN",
755
+ label: "Admin-Rolle \xFCbertragen",
756
+ severity: "high"
757
+ },
758
+ {
759
+ key: "PLATFORM_EMAIL_PROVIDER_CREATE",
760
+ label: "Plattform-Absender angelegt",
761
+ severity: "medium"
762
+ },
763
+ {
764
+ key: "PLATFORM_EMAIL_PROVIDER_UPDATE",
765
+ label: "Plattform-Absender ge\xE4ndert",
766
+ severity: "medium"
767
+ },
768
+ {
769
+ key: "PLATFORM_EMAIL_PROVIDER_DELETE",
770
+ label: "Plattform-Absender gel\xF6scht",
771
+ severity: "medium"
772
+ },
773
+ {
774
+ key: "PLATFORM_EMAIL_PROVIDER_TEST",
775
+ label: "Plattform-Absender Test-Versand",
776
+ severity: "low"
777
+ },
778
+ {
779
+ key: "EMAIL_HISTORY_DELETE",
780
+ label: "Plattform-E-Mail aus Verlauf entfernt",
781
+ severity: "medium"
782
+ },
783
+ {
784
+ key: "EMAIL_HISTORY_RESEND",
785
+ label: "Plattform-E-Mail erneut versendet",
786
+ severity: "low"
787
+ }
788
+ ]
789
+ }
790
+ };
791
+
792
+ // src/admin/admin-manifest.module.ts
793
+ import { Controller as Controller2, Get as Get2, Header, Headers, HttpCode, HttpStatus, Inject as Inject6, Module as Module2, Post, Res, UseGuards } from "@nestjs/common";
794
+ function _ts_decorate8(decorators, target, key, desc) {
795
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
796
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
797
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
798
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
799
+ }
800
+ __name(_ts_decorate8, "_ts_decorate");
801
+ function _ts_metadata6(k, v) {
802
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
803
+ }
804
+ __name(_ts_metadata6, "_ts_metadata");
805
+ function _ts_param6(paramIndex, decorator) {
806
+ return function(target, key) {
807
+ decorator(target, key, paramIndex);
808
+ };
809
+ }
810
+ __name(_ts_param6, "_ts_param");
811
+ function asConfigProvider(impl) {
812
+ if (typeof impl === "object" && impl !== null && "useFactory" in impl && typeof impl.useFactory === "function") {
813
+ return {
814
+ provide: ADMIN_MANIFEST_CONFIG,
815
+ useFactory: impl.useFactory,
816
+ inject: impl.inject
817
+ };
818
+ }
819
+ return {
820
+ provide: ADMIN_MANIFEST_CONFIG,
821
+ useValue: impl
822
+ };
823
+ }
824
+ __name(asConfigProvider, "asConfigProvider");
825
+ function buildManifestController(guards, reloadGuards) {
826
+ const reloadChain = [
827
+ ...guards,
828
+ ...reloadGuards
829
+ ];
830
+ let GeneratedAdminManifestController = class GeneratedAdminManifestController {
831
+ static {
832
+ __name(this, "GeneratedAdminManifestController");
833
+ }
834
+ manifest;
835
+ // Explicit @Inject instead of type reflection: tsup/esbuild do not emit
836
+ // `design:paramtypes` metadata, so Nest cannot otherwise resolve the
837
+ // service type at the constructor.
838
+ constructor(manifest) {
839
+ this.manifest = manifest;
840
+ }
841
+ getManifest(ifNoneMatch, res) {
842
+ const m = this.manifest.getManifest();
843
+ const etag = `"${m.build.manifestHash}"`;
844
+ res.header("ETag", etag);
845
+ if (ifNoneMatch && ifNoneMatch === etag) {
846
+ res.status(HttpStatus.NOT_MODIFIED);
847
+ return null;
848
+ }
849
+ return m;
850
+ }
851
+ reload() {
852
+ const m = this.manifest.rebuild();
853
+ return {
854
+ manifestHash: m.build.manifestHash,
855
+ reloadedAt: (/* @__PURE__ */ new Date()).toISOString()
856
+ };
857
+ }
858
+ };
859
+ _ts_decorate8([
860
+ Get2("manifest"),
861
+ Header("Cache-Control", "private, max-age=60, must-revalidate"),
862
+ _ts_param6(0, Headers("if-none-match")),
863
+ _ts_param6(1, Res({
864
+ passthrough: true
865
+ })),
866
+ _ts_metadata6("design:type", Function),
867
+ _ts_metadata6("design:paramtypes", [
868
+ Object,
869
+ typeof HttpResponseLike === "undefined" ? Object : HttpResponseLike
870
+ ]),
871
+ _ts_metadata6("design:returntype", void 0)
872
+ ], GeneratedAdminManifestController.prototype, "getManifest", null);
873
+ _ts_decorate8([
874
+ Post("manifest/reload"),
875
+ UseGuards(...reloadChain),
876
+ HttpCode(HttpStatus.OK),
877
+ _ts_metadata6("design:type", Function),
878
+ _ts_metadata6("design:paramtypes", []),
879
+ _ts_metadata6("design:returntype", void 0)
880
+ ], GeneratedAdminManifestController.prototype, "reload", null);
881
+ GeneratedAdminManifestController = _ts_decorate8([
882
+ Controller2("admin"),
883
+ UseGuards(...guards),
884
+ _ts_param6(0, Inject6(AdminManifestService)),
885
+ _ts_metadata6("design:type", Function),
886
+ _ts_metadata6("design:paramtypes", [
887
+ typeof AdminManifestService === "undefined" ? Object : AdminManifestService
888
+ ])
889
+ ], GeneratedAdminManifestController);
890
+ return GeneratedAdminManifestController;
891
+ }
892
+ __name(buildManifestController, "buildManifestController");
893
+ var AdminManifestModule = class _AdminManifestModule {
894
+ static {
895
+ __name(this, "AdminManifestModule");
896
+ }
897
+ static forRoot(options) {
898
+ const includeManifestController = options.includeManifestController ?? true;
899
+ const registerPlatformCore = options.registerPlatformCore ?? true;
900
+ const controllers = [
901
+ AdminPublicBootController
902
+ ];
903
+ if (includeManifestController) {
904
+ if (options.guards === void 0) {
905
+ throw new Error("AdminManifestModule.forRoot: `guards` ist Pflicht, wenn `includeManifestController` aktiv ist (Default `true`). Setze `guards: [JwtAuthGuard, SuperAdminGuard]` (oder analog) \u2014 oder `guards: []`, um den Endpoint absichtlich auth-frei zu betreiben. Alternative: `includeManifestController: false` und einen eigenen Wrapping-Controller registrieren.");
906
+ }
907
+ controllers.push(buildManifestController(options.guards, options.reloadGuards ?? []));
908
+ }
909
+ const providers = [
910
+ asConfigProvider(options.config),
911
+ AdminManifestService,
912
+ ...options.extraProviders ?? []
913
+ ];
914
+ if (registerPlatformCore) {
915
+ providers.push({
916
+ provide: PLATFORM_CORE_CONTRIBUTION_TOKEN,
917
+ useValue: PLATFORM_CORE_MANIFEST_CONTRIBUTION
918
+ });
919
+ }
920
+ return {
921
+ module: _AdminManifestModule,
922
+ global: options.global ?? false,
923
+ imports: options.imports ?? [],
924
+ controllers,
925
+ providers,
926
+ exports: [
927
+ ADMIN_MANIFEST_CONFIG,
928
+ AdminManifestService
929
+ ]
930
+ };
931
+ }
932
+ };
933
+ AdminManifestModule = _ts_decorate8([
934
+ Module2({})
935
+ ], AdminManifestModule);
936
+
937
+ export {
938
+ SuperAdminGuard,
939
+ MfaService,
940
+ REQUIRE_MFA_KEY,
941
+ RequireMfa,
942
+ MfaGuard,
943
+ AdminBypassRlsInterceptor,
944
+ AdminModule,
945
+ ADMIN_MANIFEST_CONFIG,
946
+ PLATFORM_CORE_CONTRIBUTION_TOKEN,
947
+ AdminManifestService,
948
+ AdminPublicBootController,
949
+ PLATFORM_CORE_MANIFEST_CONTRIBUTION,
950
+ AdminManifestModule
951
+ };