@saasicat/cli 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.
package/dist/index.js ADDED
@@ -0,0 +1,2212 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/tokens.ts
5
+ var CLI_CONTEXT_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/Config");
6
+ var USER_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/UserPort");
7
+ var USER_MANAGEMENT_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/UserManagementPort");
8
+ var AUDIT_QUERY_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/AuditQueryPort");
9
+ var DOCTOR_CHECKS_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/DoctorChecks");
10
+ var MANIFEST_ACCESS_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/ManifestAccessPort");
11
+ var MANIFEST_CHECKS_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-cli/ManifestChecks");
12
+
13
+ // src/cli-context.service.ts
14
+ import * as os from "os";
15
+ import * as readline from "readline";
16
+ import { Inject, Injectable } from "@nestjs/common";
17
+ import { AdminAuditService, MfaService } from "@saasicat/nest";
18
+ function _ts_decorate(decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ }
24
+ __name(_ts_decorate, "_ts_decorate");
25
+ function _ts_metadata(k, v) {
26
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
27
+ }
28
+ __name(_ts_metadata, "_ts_metadata");
29
+ function _ts_param(paramIndex, decorator) {
30
+ return function(target, key) {
31
+ decorator(target, key, paramIndex);
32
+ };
33
+ }
34
+ __name(_ts_param, "_ts_param");
35
+ var CliContextService = class {
36
+ static {
37
+ __name(this, "CliContextService");
38
+ }
39
+ config;
40
+ users;
41
+ mfa;
42
+ audit;
43
+ constructor(config, users, mfa, audit) {
44
+ this.config = config;
45
+ this.users = users;
46
+ this.mfa = mfa;
47
+ this.audit = audit;
48
+ }
49
+ // ---------------------------------------------------------------------
50
+ // §1 Identity
51
+ // ---------------------------------------------------------------------
52
+ resolveIdentity(asFlag) {
53
+ const fromEnv = process.env[this.config.adminEmailEnvVar] ?? "";
54
+ const email = (asFlag ?? fromEnv).trim().toLowerCase();
55
+ if (!email) {
56
+ throw new CliError("NO_IDENTITY", `Keine Admin-Identit\xE4t gesetzt. Bitte $${this.config.adminEmailEnvVar} setzen oder --as <email> \xFCbergeben.`, 2);
57
+ }
58
+ const host = os.hostname();
59
+ return {
60
+ email,
61
+ host,
62
+ actor: `cli:${email}:${host}`
63
+ };
64
+ }
65
+ /**
66
+ * Loads + validates the user for a CLI identity:
67
+ * - user exists + active
68
+ * - user has platform role SUPER_ADMIN
69
+ *
70
+ * Throws `CliError(NOT_SUPER_ADMIN, exit=2)` otherwise.
71
+ */
72
+ async ensureSuperAdmin(identity) {
73
+ const user = await this.users.findByEmail(identity.email);
74
+ if (!user || user.deletedAt || !user.isActive) {
75
+ throw new CliError("USER_NOT_FOUND", `SUPER_ADMIN-User ${identity.email} nicht gefunden oder inaktiv.`, 2);
76
+ }
77
+ if (user.platformRole !== "SUPER_ADMIN") {
78
+ throw new CliError("NOT_SUPER_ADMIN", `User ${identity.email} hat Rolle ${user.platformRole} \u2014 nur SUPER_ADMIN darf das CLI nutzen.`, 2);
79
+ }
80
+ return user;
81
+ }
82
+ // ---------------------------------------------------------------------
83
+ // §2 MFA — mandatory TOTP
84
+ // ---------------------------------------------------------------------
85
+ /**
86
+ * Prompts the user for a TOTP code and verifies it against the stored
87
+ * secret (via the platform `MfaService` → `MfaPort`).
88
+ *
89
+ * Bypass: `process.env[mfaSkipEnvVar] === '1'` AND `!isProductionEnvironment()`.
90
+ */
91
+ async requireMfa(userId) {
92
+ if (process.env[this.config.mfaSkipEnvVar] === "1" && !this.config.isProductionEnvironment()) {
93
+ return;
94
+ }
95
+ const enabled = await this.mfa.isEnabled(userId);
96
+ if (!enabled) {
97
+ throw new CliError("MFA_NOT_SET_UP", "MFA ist nicht konfiguriert. Bitte zuerst 'admin mfa-setup' ausf\xFChren.", 3);
98
+ }
99
+ const code = await this.prompt("TOTP-Code: ");
100
+ const ok2 = await this.mfa.verify({
101
+ userId,
102
+ code
103
+ });
104
+ if (!ok2) {
105
+ throw new CliError("MFA_FAILED", "TOTP-Code ung\xFCltig.", 3);
106
+ }
107
+ }
108
+ // ---------------------------------------------------------------------
109
+ // §3 Production confirmation
110
+ // ---------------------------------------------------------------------
111
+ async ensureProductionConfirmation(opts = {}) {
112
+ if (!this.config.isProductionEnvironment()) return;
113
+ if (opts.yes) return;
114
+ const answer = await this.prompt("Tippe production zur Best\xE4tigung: ");
115
+ if (answer.trim().toLowerCase() !== "production") {
116
+ throw new CliError("PRODUCTION_CONFIRM_ABORTED", "Production-Confirmation abgebrochen.", 1);
117
+ }
118
+ }
119
+ // ---------------------------------------------------------------------
120
+ // §5 Audit
121
+ // ---------------------------------------------------------------------
122
+ /**
123
+ * Writes an audit-log entry with the CLI actor tag. Wrapper over
124
+ * `AdminAuditService.log` with automatic `fromCli` construction.
125
+ */
126
+ async log(input) {
127
+ const actor = this.audit.fromCli({
128
+ id: input.userId,
129
+ email: input.identity.email
130
+ });
131
+ await this.audit.log({
132
+ actor,
133
+ entity: input.entity,
134
+ entityId: input.entityId,
135
+ action: input.action,
136
+ changes: input.changes
137
+ });
138
+ }
139
+ // ---------------------------------------------------------------------
140
+ // Output helpers (§4)
141
+ // ---------------------------------------------------------------------
142
+ table(rows) {
143
+ if (rows.length === 0) {
144
+ console.log("\u2014 keine Eintr\xE4ge \u2014");
145
+ return;
146
+ }
147
+ console.table(rows);
148
+ }
149
+ /**
150
+ * Reads a line from stdin. Override hook for tests: set
151
+ * `process.env.SAAS_PLATFORM_CLI_PROMPT_REPLY` to a reply, then
152
+ * the method succeeds without interaction.
153
+ */
154
+ async prompt(question) {
155
+ const testReply = process.env.SAAS_PLATFORM_CLI_PROMPT_REPLY;
156
+ if (testReply !== void 0) return testReply;
157
+ const rl = readline.createInterface({
158
+ input: process.stdin,
159
+ output: process.stdout
160
+ });
161
+ return new Promise((resolve) => {
162
+ rl.question(question, (answer) => {
163
+ rl.close();
164
+ resolve(answer);
165
+ });
166
+ });
167
+ }
168
+ };
169
+ CliContextService = _ts_decorate([
170
+ Injectable(),
171
+ _ts_param(0, Inject(CLI_CONTEXT_CONFIG_TOKEN)),
172
+ _ts_param(1, Inject(USER_PORT_TOKEN)),
173
+ _ts_metadata("design:type", Function),
174
+ _ts_metadata("design:paramtypes", [
175
+ typeof CliContextConfig === "undefined" ? Object : CliContextConfig,
176
+ typeof UserPort === "undefined" ? Object : UserPort,
177
+ typeof MfaService === "undefined" ? Object : MfaService,
178
+ typeof AdminAuditService === "undefined" ? Object : AdminAuditService
179
+ ])
180
+ ], CliContextService);
181
+ var CliError = class extends Error {
182
+ static {
183
+ __name(this, "CliError");
184
+ }
185
+ code;
186
+ exitCode;
187
+ constructor(code, message, exitCode) {
188
+ super(message), this.code = code, this.exitCode = exitCode;
189
+ this.name = "CliError";
190
+ }
191
+ };
192
+
193
+ // src/mfa-setup-flow.ts
194
+ import { Injectable as Injectable2 } from "@nestjs/common";
195
+ import { MfaService as MfaService2 } from "@saasicat/nest";
196
+ function _ts_decorate2(decorators, target, key, desc) {
197
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
198
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
199
+ 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;
200
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
201
+ }
202
+ __name(_ts_decorate2, "_ts_decorate");
203
+ function _ts_metadata2(k, v) {
204
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
205
+ }
206
+ __name(_ts_metadata2, "_ts_metadata");
207
+ var MfaSetupFlow = class {
208
+ static {
209
+ __name(this, "MfaSetupFlow");
210
+ }
211
+ ctx;
212
+ mfa;
213
+ constructor(ctx, mfa) {
214
+ this.ctx = ctx;
215
+ this.mfa = mfa;
216
+ }
217
+ /**
218
+ * Runs the full setup flow. Throws `CliError` subclasses on
219
+ * auth/identity/confirmation errors.
220
+ */
221
+ async run(options) {
222
+ const identity = this.ctx.resolveIdentity(options.asFlag);
223
+ const user = await this.ctx.ensureSuperAdmin(identity);
224
+ const alreadyEnabled = await this.mfa.isEnabled(user.id);
225
+ if (alreadyEnabled && !options.force) {
226
+ const answer = await this.ctx.prompt("MFA ist bereits konfiguriert. Tippe `yes`, um das Secret zu \xFCberschreiben: ");
227
+ if (answer.trim().toLowerCase() !== "yes") {
228
+ throw new CliError("MFA_SETUP_ABORTED", "Re-Setup nicht best\xE4tigt \u2014 bestehendes Secret bleibt aktiv.", 1);
229
+ }
230
+ }
231
+ const setup = await this.mfa.setup(user.id, user.email, options.issuer);
232
+ await this.ctx.log({
233
+ identity,
234
+ userId: user.id,
235
+ entity: "User",
236
+ entityId: user.id,
237
+ action: alreadyEnabled ? "MFA_SETUP_RESET" : "MFA_SETUP_COMPLETED",
238
+ changes: {
239
+ issuer: options.issuer
240
+ }
241
+ });
242
+ return {
243
+ secret: setup.secret,
244
+ otpauthUri: setup.otpauthUri,
245
+ userId: user.id,
246
+ userEmail: user.email
247
+ };
248
+ }
249
+ /**
250
+ * Helper: returns a human-readable output block with secret + otpauthUri
251
+ * for `console.log` in the consumer command. Consumers may prepend their
252
+ * own QR-code renderer (e.g. `qrcode-terminal`).
253
+ */
254
+ formatSetupResult(result) {
255
+ return [
256
+ `MFA-Setup f\xFCr ${result.userEmail} abgeschlossen.`,
257
+ "",
258
+ `Secret (Base32): ${result.secret}`,
259
+ `otpauth-URI: ${result.otpauthUri}`,
260
+ "",
261
+ "Bitte den otpauth-URI in den Authenticator (Google Authenticator,",
262
+ "1Password, \u2026) importieren oder als QR-Code in einem QR-Generator",
263
+ "rendern. Danach mit dem ersten TOTP-Code testen, dass der Login",
264
+ "funktioniert \u2014 sonst kommst du nicht mehr ans CLI."
265
+ ].join("\n");
266
+ }
267
+ };
268
+ MfaSetupFlow = _ts_decorate2([
269
+ Injectable2(),
270
+ _ts_metadata2("design:type", Function),
271
+ _ts_metadata2("design:paramtypes", [
272
+ typeof CliContextService === "undefined" ? Object : CliContextService,
273
+ typeof MfaService2 === "undefined" ? Object : MfaService2
274
+ ])
275
+ ], MfaSetupFlow);
276
+
277
+ // src/whoami-flow.ts
278
+ import { Inject as Inject2, Injectable as Injectable3 } from "@nestjs/common";
279
+ import { MfaService as MfaService3 } from "@saasicat/nest";
280
+ function _ts_decorate3(decorators, target, key, desc) {
281
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
282
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
283
+ 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;
284
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
285
+ }
286
+ __name(_ts_decorate3, "_ts_decorate");
287
+ function _ts_metadata3(k, v) {
288
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
289
+ }
290
+ __name(_ts_metadata3, "_ts_metadata");
291
+ function _ts_param2(paramIndex, decorator) {
292
+ return function(target, key) {
293
+ decorator(target, key, paramIndex);
294
+ };
295
+ }
296
+ __name(_ts_param2, "_ts_param");
297
+ var WhoAmIFlow = class {
298
+ static {
299
+ __name(this, "WhoAmIFlow");
300
+ }
301
+ config;
302
+ ctx;
303
+ mfa;
304
+ constructor(config, ctx, mfa) {
305
+ this.config = config;
306
+ this.ctx = ctx;
307
+ this.mfa = mfa;
308
+ }
309
+ async run(asFlag) {
310
+ const identity = this.ctx.resolveIdentity(asFlag);
311
+ const isProduction = this.config.isProductionEnvironment();
312
+ const mfaSkipActive = !isProduction && process.env[this.config.mfaSkipEnvVar] === "1";
313
+ let userId = null;
314
+ let isSuperAdmin = false;
315
+ let mfaEnabled = false;
316
+ try {
317
+ const user = await this.ctx.ensureSuperAdmin(identity);
318
+ userId = user.id;
319
+ isSuperAdmin = true;
320
+ mfaEnabled = await this.mfa.isEnabled(user.id);
321
+ } catch {
322
+ }
323
+ return {
324
+ email: identity.email,
325
+ host: identity.host,
326
+ actor: identity.actor,
327
+ userId,
328
+ isSuperAdmin,
329
+ mfaEnabled,
330
+ isProduction,
331
+ mfaSkipActive
332
+ };
333
+ }
334
+ formatResult(r) {
335
+ const lines = [
336
+ `Identit\xE4t: ${r.email}`,
337
+ `Host: ${r.host}`,
338
+ `Actor-Tag: ${r.actor}`,
339
+ `User-ID: ${r.userId ?? "\u2014 (User nicht gefunden)"}`,
340
+ `Plattform-Rolle: ${r.isSuperAdmin ? "SUPER_ADMIN \u2713" : "\u2014 (kein SUPER_ADMIN!)"}`,
341
+ `MFA konfiguriert: ${r.mfaEnabled ? "\u2713" : "\u2717 \u2014 bitte `admin mfa-setup` ausf\xFChren"}`,
342
+ `Environment: ${r.isProduction ? "PRODUCTION" : "non-production"}`
343
+ ];
344
+ if (r.mfaSkipActive) {
345
+ lines.push("\u26A0 MFA-Bypass aktiv (SKIP-Env-Var gesetzt, non-prod)");
346
+ }
347
+ return lines.join("\n");
348
+ }
349
+ };
350
+ WhoAmIFlow = _ts_decorate3([
351
+ Injectable3(),
352
+ _ts_param2(0, Inject2(CLI_CONTEXT_CONFIG_TOKEN)),
353
+ _ts_metadata3("design:type", Function),
354
+ _ts_metadata3("design:paramtypes", [
355
+ typeof CliContextConfig === "undefined" ? Object : CliContextConfig,
356
+ typeof CliContextService === "undefined" ? Object : CliContextService,
357
+ typeof MfaService3 === "undefined" ? Object : MfaService3
358
+ ])
359
+ ], WhoAmIFlow);
360
+
361
+ // src/audit-tail-flow.ts
362
+ import { Inject as Inject3, Injectable as Injectable4 } from "@nestjs/common";
363
+ function _ts_decorate4(decorators, target, key, desc) {
364
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
365
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
366
+ 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;
367
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
368
+ }
369
+ __name(_ts_decorate4, "_ts_decorate");
370
+ function _ts_metadata4(k, v) {
371
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
372
+ }
373
+ __name(_ts_metadata4, "_ts_metadata");
374
+ function _ts_param3(paramIndex, decorator) {
375
+ return function(target, key) {
376
+ decorator(target, key, paramIndex);
377
+ };
378
+ }
379
+ __name(_ts_param3, "_ts_param");
380
+ var AuditTailFlow = class {
381
+ static {
382
+ __name(this, "AuditTailFlow");
383
+ }
384
+ auditQuery;
385
+ constructor(auditQuery) {
386
+ this.auditQuery = auditQuery;
387
+ }
388
+ async run(options = {}) {
389
+ const filter = {};
390
+ if (options.actor) filter.actorTag = options.actor;
391
+ if (options.action) filter.action = options.action;
392
+ if (options.entity) filter.entity = options.entity;
393
+ if (options.since) filter.from = options.since;
394
+ if (options.limit) filter.pageSize = options.limit;
395
+ return this.auditQuery.list(filter);
396
+ }
397
+ /** Format the result as an ASCII table for `console.table`. */
398
+ formatRows(entries) {
399
+ return entries.map((e) => ({
400
+ createdAt: e.createdAt,
401
+ actor: e.actorTag ?? "\u2014",
402
+ entity: e.entity,
403
+ entityId: this.truncate(e.entityId, 12),
404
+ action: e.action
405
+ }));
406
+ }
407
+ truncate(s, maxLen) {
408
+ return s.length > maxLen ? s.slice(0, maxLen - 1) + "\u2026" : s;
409
+ }
410
+ };
411
+ AuditTailFlow = _ts_decorate4([
412
+ Injectable4(),
413
+ _ts_param3(0, Inject3(AUDIT_QUERY_PORT_TOKEN)),
414
+ _ts_metadata4("design:type", Function),
415
+ _ts_metadata4("design:paramtypes", [
416
+ typeof AuditQueryPort === "undefined" ? Object : AuditQueryPort
417
+ ])
418
+ ], AuditTailFlow);
419
+
420
+ // src/doctor-flow.ts
421
+ import { Inject as Inject4, Injectable as Injectable5 } from "@nestjs/common";
422
+ function _ts_decorate5(decorators, target, key, desc) {
423
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
424
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
425
+ 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;
426
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
427
+ }
428
+ __name(_ts_decorate5, "_ts_decorate");
429
+ function _ts_metadata5(k, v) {
430
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
431
+ }
432
+ __name(_ts_metadata5, "_ts_metadata");
433
+ function _ts_param4(paramIndex, decorator) {
434
+ return function(target, key) {
435
+ decorator(target, key, paramIndex);
436
+ };
437
+ }
438
+ __name(_ts_param4, "_ts_param");
439
+ var DoctorFlow = class {
440
+ static {
441
+ __name(this, "DoctorFlow");
442
+ }
443
+ checks;
444
+ constructor(checks) {
445
+ this.checks = checks;
446
+ }
447
+ async run() {
448
+ const results = [];
449
+ let overall = "ok";
450
+ for (const check of this.checks) {
451
+ try {
452
+ const r = await check.run();
453
+ results.push({
454
+ id: check.id,
455
+ label: check.label,
456
+ ...r
457
+ });
458
+ overall = aggregateSeverity(overall, r.severity);
459
+ } catch (err2) {
460
+ const message = err2 instanceof Error ? err2.message : String(err2);
461
+ results.push({
462
+ id: check.id,
463
+ label: check.label,
464
+ severity: "error",
465
+ message: `Check threw an exception: ${message}`
466
+ });
467
+ overall = "error";
468
+ }
469
+ }
470
+ return {
471
+ overall,
472
+ checks: results
473
+ };
474
+ }
475
+ /** Returns the appropriate CLI exit code: 0 for `ok`/`warning`, 4 for `error`. */
476
+ exitCodeFor(report) {
477
+ return report.overall === "error" ? 4 : 0;
478
+ }
479
+ formatReport(report) {
480
+ const lines = [
481
+ `Doctor-Check (Gesamtstatus: ${report.overall.toUpperCase()})`,
482
+ ""
483
+ ];
484
+ for (const c of report.checks) {
485
+ const icon = c.severity === "ok" ? "\u2713" : c.severity === "warning" ? "\u26A0" : "\u2717";
486
+ lines.push(` ${icon} ${c.label}: ${c.message}`);
487
+ }
488
+ return lines.join("\n");
489
+ }
490
+ };
491
+ DoctorFlow = _ts_decorate5([
492
+ Injectable5(),
493
+ _ts_param4(0, Inject4(DOCTOR_CHECKS_TOKEN)),
494
+ _ts_metadata5("design:type", Function),
495
+ _ts_metadata5("design:paramtypes", [
496
+ Array
497
+ ])
498
+ ], DoctorFlow);
499
+ function aggregateSeverity(a, b) {
500
+ if (a === "error" || b === "error") return "error";
501
+ if (a === "warning" || b === "warning") return "warning";
502
+ return "ok";
503
+ }
504
+ __name(aggregateSeverity, "aggregateSeverity");
505
+
506
+ // src/manifest-checks.ts
507
+ var COMPONENT_KEY_PATTERN = /^[a-z][a-z0-9]*([.-][a-z0-9]+)+$/;
508
+ var ACTION_KEY_PATTERN = /^[A-Z][A-Z0-9_]+$/;
509
+ var TENANT_ACTION_KEY_PATTERN = /^[a-z][a-zA-Z0-9_]*(\.[a-z][a-zA-Z0-9_]*)+$/;
510
+ var CAPABILITY_PATTERN = /^[a-z][a-zA-Z0-9_]*(\.[a-z][a-zA-Z0-9_]*)+$/;
511
+ var ROUTE_PREFIX = "/admin";
512
+ function ok(message) {
513
+ return {
514
+ severity: "ok",
515
+ message
516
+ };
517
+ }
518
+ __name(ok, "ok");
519
+ function err(message, paths) {
520
+ return {
521
+ severity: "error",
522
+ message,
523
+ paths
524
+ };
525
+ }
526
+ __name(err, "err");
527
+ function allProjectPages(m) {
528
+ return m.navigation?.projectPages ?? [];
529
+ }
530
+ __name(allProjectPages, "allProjectPages");
531
+ function allKpiCards(m) {
532
+ return m.dashboard?.kpiCards ?? [];
533
+ }
534
+ __name(allKpiCards, "allKpiCards");
535
+ function allTenantActions(m) {
536
+ return m.tenants?.actions ?? [];
537
+ }
538
+ __name(allTenantActions, "allTenantActions");
539
+ function allTenantColumns(m) {
540
+ return m.tenants?.columns ?? [];
541
+ }
542
+ __name(allTenantColumns, "allTenantColumns");
543
+ function allAuditActions(m) {
544
+ return m.audit?.actions ?? [];
545
+ }
546
+ __name(allAuditActions, "allAuditActions");
547
+ function allCapabilities(m) {
548
+ return Object.keys(m.capabilities ?? {});
549
+ }
550
+ __name(allCapabilities, "allCapabilities");
551
+ var DEFAULT_MANIFEST_CHECKS = [
552
+ {
553
+ id: "manifest.schema-version",
554
+ label: "schemaVersion ist 1",
555
+ run: /* @__PURE__ */ __name((m) => m.schemaVersion === 1 ? ok("schemaVersion=1") : err(`Unerwartete schemaVersion ${m.schemaVersion}`), "run")
556
+ },
557
+ {
558
+ id: "manifest.hash-format",
559
+ label: "manifestHash folgt sha256-<base64url>-Pattern",
560
+ run: /* @__PURE__ */ __name((m) => {
561
+ const hash = m.build?.manifestHash;
562
+ if (!hash) return err("manifestHash fehlt");
563
+ return /^sha256-[A-Za-z0-9_-]+$/.test(hash) ? ok(hash) : err(`manifestHash hat falsches Format: ${hash}`);
564
+ }, "run")
565
+ },
566
+ {
567
+ id: "manifest.project-page-component-keys",
568
+ label: "ProjectPage.componentKey-Format (lowercase-hyphenated ODER namespace.dot)",
569
+ run: /* @__PURE__ */ __name((m) => {
570
+ const bad = [];
571
+ for (const p of allProjectPages(m)) {
572
+ if (!COMPONENT_KEY_PATTERN.test(p.componentKey)) bad.push(p.componentKey);
573
+ }
574
+ return bad.length === 0 ? ok(`${allProjectPages(m).length} ProjectPage(s) ok`) : err(`${bad.length} componentKey(s) verletzen das Pattern`, bad);
575
+ }, "run")
576
+ },
577
+ {
578
+ id: "manifest.tenant-action-keys",
579
+ label: "TenantAction.actionKey-Format (domain.action \u2014 SPEC \xA74.2.1)",
580
+ run: /* @__PURE__ */ __name((m) => {
581
+ const bad = [];
582
+ for (const a of allTenantActions(m)) {
583
+ if (!TENANT_ACTION_KEY_PATTERN.test(a.actionKey)) bad.push(a.actionKey);
584
+ }
585
+ return bad.length === 0 ? ok("alle actionKeys folgen domain.action") : err(`${bad.length} actionKey(s) verletzen das Pattern`, bad);
586
+ }, "run")
587
+ },
588
+ {
589
+ id: "manifest.audit-action-keys",
590
+ label: "AuditAction.key-Format (SCREAMING_SNAKE_CASE)",
591
+ run: /* @__PURE__ */ __name((m) => {
592
+ const bad = [];
593
+ for (const a of allAuditActions(m)) {
594
+ if (!ACTION_KEY_PATTERN.test(a.key)) bad.push(a.key);
595
+ }
596
+ return bad.length === 0 ? ok("alle AuditAction.keys SCREAMING_SNAKE_CASE") : err(`${bad.length} AuditAction.key(s) verletzen das Pattern`, bad);
597
+ }, "run")
598
+ },
599
+ {
600
+ id: "manifest.capabilities-pattern",
601
+ label: "Capability-Pattern <domain>.<action> (SPEC \xA74.2.1)",
602
+ run: /* @__PURE__ */ __name((m) => {
603
+ const bad = allCapabilities(m).filter((c) => !CAPABILITY_PATTERN.test(c));
604
+ return bad.length === 0 ? ok(`${allCapabilities(m).length} Capabilities ok`) : err(`${bad.length} Capability/-ies verletzen das Pattern`, bad);
605
+ }, "run")
606
+ },
607
+ {
608
+ id: "manifest.required-capabilities-known",
609
+ label: "requiredCapability-Referenzen existieren in capabilities-Map",
610
+ run: /* @__PURE__ */ __name((m) => {
611
+ const known = new Set(allCapabilities(m));
612
+ const bad = [];
613
+ const visit = /* @__PURE__ */ __name((cap, ctx) => {
614
+ if (cap && !known.has(cap)) bad.push(`${ctx ?? "?"}: ${cap}`);
615
+ }, "visit");
616
+ for (const p of allProjectPages(m)) visit(p.requiredCapability, p.id);
617
+ for (const k of allKpiCards(m)) visit(k.requiredCapability, k.id);
618
+ for (const a of allTenantActions(m)) visit(a.requiredCapability, a.id);
619
+ for (const c of allTenantColumns(m)) visit(c.requiredCapability, c.key);
620
+ return bad.length === 0 ? ok("alle requiredCapability-Refs aufgel\xF6st") : err(`${bad.length} unbekannte Capability-Ref(s)`, bad);
621
+ }, "run")
622
+ },
623
+ {
624
+ id: "manifest.route-prefix",
625
+ label: "ProjectPage.route beginnt mit /admin",
626
+ run: /* @__PURE__ */ __name((m) => {
627
+ const bad = [];
628
+ for (const p of allProjectPages(m)) {
629
+ if (!p.route.startsWith(ROUTE_PREFIX)) bad.push(p.route);
630
+ }
631
+ return bad.length === 0 ? ok("alle ProjectPage-Routes unter /admin") : err(`${bad.length} Route(s) ohne /admin-Prefix`, bad);
632
+ }, "run")
633
+ },
634
+ {
635
+ id: "manifest.kpi-slot-priority",
636
+ label: "KpiCard.slotPriority (falls gesetzt) ist endliche Zahl",
637
+ run: /* @__PURE__ */ __name((m) => {
638
+ const bad = [];
639
+ for (const k of allKpiCards(m)) {
640
+ if (k.slotPriority !== void 0 && !Number.isFinite(k.slotPriority)) {
641
+ bad.push(k.id);
642
+ }
643
+ }
644
+ return bad.length === 0 ? ok("alle slotPriority-Werte endlich") : err(`${bad.length} KpiCard(s) mit ung\xFCltiger slotPriority`, bad);
645
+ }, "run")
646
+ },
647
+ {
648
+ id: "manifest.unique-project-page-ids",
649
+ label: "ProjectPage.id ist unique",
650
+ run: /* @__PURE__ */ __name((m) => {
651
+ const seen = /* @__PURE__ */ new Map();
652
+ for (const p of allProjectPages(m)) {
653
+ seen.set(p.id, (seen.get(p.id) ?? 0) + 1);
654
+ }
655
+ const dups = [
656
+ ...seen.entries()
657
+ ].filter(([, n]) => n > 1).map(([k]) => k);
658
+ return dups.length === 0 ? ok("alle ProjectPage.id eindeutig") : err(`${dups.length} doppelte ProjectPage.id`, dups);
659
+ }, "run")
660
+ },
661
+ {
662
+ id: "manifest.unique-action-keys",
663
+ label: "actionKeys sind je Namespace (TenantAction / AuditAction) eindeutig",
664
+ run: /* @__PURE__ */ __name((m) => {
665
+ const dups = [];
666
+ const tenantSeen = /* @__PURE__ */ new Map();
667
+ for (const a of allTenantActions(m)) {
668
+ tenantSeen.set(a.actionKey, (tenantSeen.get(a.actionKey) ?? 0) + 1);
669
+ }
670
+ for (const [k, n] of tenantSeen) {
671
+ if (n > 1) dups.push(`TenantAction:${k}`);
672
+ }
673
+ const auditSeen = /* @__PURE__ */ new Map();
674
+ for (const a of allAuditActions(m)) {
675
+ auditSeen.set(a.key, (auditSeen.get(a.key) ?? 0) + 1);
676
+ }
677
+ for (const [k, n] of auditSeen) {
678
+ if (n > 1) dups.push(`AuditAction:${k}`);
679
+ }
680
+ return dups.length === 0 ? ok("alle actionKeys je Namespace eindeutig") : err(`${dups.length} doppelte actionKey(s)`, dups);
681
+ }, "run")
682
+ },
683
+ {
684
+ id: "manifest.tenant-columns-batchable",
685
+ label: "TenantColumns haben endpoint-Pfad f\xFCr Batch-Fetch",
686
+ run: /* @__PURE__ */ __name((m) => {
687
+ const bad = [];
688
+ for (const c of allTenantColumns(m)) {
689
+ if (!c.endpoint || c.endpoint.trim().length === 0) bad.push(c.key);
690
+ else if (c.endpoint.includes("{slug}") || c.endpoint.includes("{tenantId}")) {
691
+ bad.push(`${c.key} (per-Tenant statt batch)`);
692
+ }
693
+ }
694
+ return bad.length === 0 ? ok("alle TenantColumns batch-f\xE4hig") : err(`${bad.length} TenantColumn(s) verletzen Batch-Pflicht`, bad);
695
+ }, "run")
696
+ }
697
+ ];
698
+
699
+ // src/manifest-cli-flow.ts
700
+ import { Inject as Inject5, Injectable as Injectable6 } from "@nestjs/common";
701
+ function _ts_decorate6(decorators, target, key, desc) {
702
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
703
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
704
+ 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;
705
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
706
+ }
707
+ __name(_ts_decorate6, "_ts_decorate");
708
+ function _ts_metadata6(k, v) {
709
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
710
+ }
711
+ __name(_ts_metadata6, "_ts_metadata");
712
+ function _ts_param5(paramIndex, decorator) {
713
+ return function(target, key) {
714
+ decorator(target, key, paramIndex);
715
+ };
716
+ }
717
+ __name(_ts_param5, "_ts_param");
718
+ var ManifestCliFlow = class {
719
+ static {
720
+ __name(this, "ManifestCliFlow");
721
+ }
722
+ access;
723
+ checks;
724
+ constructor(access, checks) {
725
+ this.access = access;
726
+ this.checks = checks;
727
+ }
728
+ /** `<app> manifest dump` — JSON output of the current manifest. */
729
+ dump() {
730
+ return this.access.getManifest();
731
+ }
732
+ /**
733
+ * `<app> manifest hash` — canonical manifestHash value. Returns
734
+ * the value from `build.manifestHash`. Consumers can pin this in CI
735
+ * (`expected-hash.txt`) and check for drift.
736
+ */
737
+ hash() {
738
+ const m = this.access.getManifest();
739
+ const h = m.build?.manifestHash;
740
+ if (!h) throw new Error("manifestHash fehlt im Manifest \u2014 Boot-Zeit-Bug?");
741
+ return h;
742
+ }
743
+ /**
744
+ * `<app> manifest validate` — returns `true` when all structures
745
+ * are present. Deeper schema validation runs separately via Ajv with
746
+ * `@saasicat/spec/schemas/admin-manifest.schema.json`;
747
+ * this helper provides the quick diagnostic without the Ajv cost.
748
+ */
749
+ validate() {
750
+ const m = this.access.getManifest();
751
+ if (m.schemaVersion !== 1) {
752
+ return {
753
+ ok: false,
754
+ reason: `Unerwartete schemaVersion ${m.schemaVersion}`
755
+ };
756
+ }
757
+ if (!m.project?.key) {
758
+ return {
759
+ ok: false,
760
+ reason: "Kein `project.key` im Manifest"
761
+ };
762
+ }
763
+ if (!m.build?.manifestHash) {
764
+ return {
765
+ ok: false,
766
+ reason: "manifestHash fehlt"
767
+ };
768
+ }
769
+ return {
770
+ ok: true
771
+ };
772
+ }
773
+ /**
774
+ * `<app> manifest diff <expected.json>` — flat diff over the two
775
+ * manifest hashes plus list differences for top-level fields. Returns
776
+ * `null` when the manifests are identical.
777
+ */
778
+ diff(expected) {
779
+ const current = this.access.getManifest();
780
+ if (current.build?.manifestHash === expected.build?.manifestHash) return null;
781
+ const currentKeys = collectComponentKeys(current);
782
+ const expectedKeys = collectComponentKeys(expected);
783
+ return {
784
+ currentHash: current.build?.manifestHash ?? null,
785
+ expectedHash: expected.build?.manifestHash ?? null,
786
+ componentKeysAdded: [
787
+ ...currentKeys
788
+ ].filter((k) => !expectedKeys.has(k)).sort(),
789
+ componentKeysRemoved: [
790
+ ...expectedKeys
791
+ ].filter((k) => !currentKeys.has(k)).sort()
792
+ };
793
+ }
794
+ /**
795
+ * `<app> manifest check` — runs all registered manifest checks.
796
+ * Aggregates severity (ok/warning/error) into `overall`. The consumer
797
+ * maps `error` to exit code 7 (drift) per `cli-conventions.md` §6.
798
+ */
799
+ async runChecks() {
800
+ const manifest = this.access.getManifest();
801
+ const checks = [];
802
+ let overall = "ok";
803
+ for (const check of this.checks) {
804
+ try {
805
+ const r = check.run(manifest);
806
+ checks.push({
807
+ id: check.id,
808
+ label: check.label,
809
+ ...r
810
+ });
811
+ overall = aggregate(overall, r.severity);
812
+ } catch (err2) {
813
+ const message = err2 instanceof Error ? err2.message : String(err2);
814
+ checks.push({
815
+ id: check.id,
816
+ label: check.label,
817
+ severity: "error",
818
+ message: `Check warf eine Exception: ${message}`
819
+ });
820
+ overall = "error";
821
+ }
822
+ }
823
+ return {
824
+ overall,
825
+ checks
826
+ };
827
+ }
828
+ /** Returns the appropriate CLI exit code: 0 for `ok`/`warning`, 7 for `error` (drift). */
829
+ exitCodeFor(report) {
830
+ return report.overall === "error" ? 7 : 0;
831
+ }
832
+ formatReport(report) {
833
+ const lines = [
834
+ `Manifest-Check (Gesamtstatus: ${report.overall.toUpperCase()})`,
835
+ ""
836
+ ];
837
+ for (const c of report.checks) {
838
+ const icon = c.severity === "ok" ? "\u2713" : c.severity === "warning" ? "\u26A0" : "\u2717";
839
+ lines.push(` ${icon} ${c.label}: ${c.message}`);
840
+ if (c.paths && c.paths.length > 0) {
841
+ for (const p of c.paths) lines.push(` \xB7 ${p}`);
842
+ }
843
+ }
844
+ return lines.join("\n");
845
+ }
846
+ };
847
+ ManifestCliFlow = _ts_decorate6([
848
+ Injectable6(),
849
+ _ts_param5(0, Inject5(MANIFEST_ACCESS_PORT_TOKEN)),
850
+ _ts_param5(1, Inject5(MANIFEST_CHECKS_TOKEN)),
851
+ _ts_metadata6("design:type", Function),
852
+ _ts_metadata6("design:paramtypes", [
853
+ typeof ManifestAccessPort === "undefined" ? Object : ManifestAccessPort,
854
+ Array
855
+ ])
856
+ ], ManifestCliFlow);
857
+ function aggregate(a, b) {
858
+ if (a === "error" || b === "error") return "error";
859
+ if (a === "warning" || b === "warning") return "warning";
860
+ return "ok";
861
+ }
862
+ __name(aggregate, "aggregate");
863
+ function collectComponentKeys(m) {
864
+ const keys = /* @__PURE__ */ new Set();
865
+ for (const p of m.navigation?.projectPages ?? []) keys.add(p.componentKey);
866
+ return keys;
867
+ }
868
+ __name(collectComponentKeys, "collectComponentKeys");
869
+
870
+ // src/default-doctor-checks.ts
871
+ import { Inject as Inject6, Injectable as Injectable7 } from "@nestjs/common";
872
+ import { AdminManifestService, DISCOVERY_SNAPSHOT_TOKEN, PLAN_CATALOG_TOKEN } from "@saasicat/nest";
873
+ function _ts_decorate7(decorators, target, key, desc) {
874
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
875
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
876
+ 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;
877
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
878
+ }
879
+ __name(_ts_decorate7, "_ts_decorate");
880
+ function _ts_metadata7(k, v) {
881
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
882
+ }
883
+ __name(_ts_metadata7, "_ts_metadata");
884
+ function _ts_param6(paramIndex, decorator) {
885
+ return function(target, key) {
886
+ decorator(target, key, paramIndex);
887
+ };
888
+ }
889
+ __name(_ts_param6, "_ts_param");
890
+ var PlanCatalogDoctorCheck = class {
891
+ static {
892
+ __name(this, "PlanCatalogDoctorCheck");
893
+ }
894
+ catalog;
895
+ id = "platform.plan-catalog";
896
+ label = "Plan-Catalog im DI";
897
+ constructor(catalog) {
898
+ this.catalog = catalog;
899
+ }
900
+ async run() {
901
+ const plans = this.catalog?.plans ?? [];
902
+ if (plans.length === 0) {
903
+ return {
904
+ severity: "error",
905
+ message: "PlanCatalog enth\xE4lt keine Pl\xE4ne \u2014 Onboarding-Pricing-Page wird leer."
906
+ };
907
+ }
908
+ return {
909
+ severity: "ok",
910
+ message: `${plans.length} Plan(s), ${this.catalog.features?.length ?? 0} Feature(s) geladen.`,
911
+ details: {
912
+ projectKey: this.catalog.projectKey,
913
+ planIds: plans.map((p) => p.id)
914
+ }
915
+ };
916
+ }
917
+ };
918
+ PlanCatalogDoctorCheck = _ts_decorate7([
919
+ Injectable7(),
920
+ _ts_param6(0, Inject6(PLAN_CATALOG_TOKEN)),
921
+ _ts_metadata7("design:type", Function),
922
+ _ts_metadata7("design:paramtypes", [
923
+ typeof PlanCatalog === "undefined" ? Object : PlanCatalog
924
+ ])
925
+ ], PlanCatalogDoctorCheck);
926
+ var DiscoverySnapshotDoctorCheck = class {
927
+ static {
928
+ __name(this, "DiscoverySnapshotDoctorCheck");
929
+ }
930
+ snapshot;
931
+ id = "platform.discovery-snapshot";
932
+ label = "Discovery-Snapshot beim Boot";
933
+ constructor(snapshot) {
934
+ this.snapshot = snapshot;
935
+ }
936
+ async run() {
937
+ const caps = this.snapshot?.capabilities ?? [];
938
+ if (caps.length === 0) {
939
+ return {
940
+ severity: "warning",
941
+ message: "Keine Capabilities entdeckt \u2014 Decorator-tragende Module evtl. nicht in AppModule.imports[]."
942
+ };
943
+ }
944
+ return {
945
+ severity: "ok",
946
+ message: `${caps.length} Capabilities, ${this.snapshot.features?.length ?? 0} Features, ${this.snapshot.quotas?.length ?? 0} Quotas.`
947
+ };
948
+ }
949
+ };
950
+ DiscoverySnapshotDoctorCheck = _ts_decorate7([
951
+ Injectable7(),
952
+ _ts_param6(0, Inject6(DISCOVERY_SNAPSHOT_TOKEN)),
953
+ _ts_metadata7("design:type", Function),
954
+ _ts_metadata7("design:paramtypes", [
955
+ typeof DiscoverySnapshot === "undefined" ? Object : DiscoverySnapshot
956
+ ])
957
+ ], DiscoverySnapshotDoctorCheck);
958
+ var UserPortDoctorCheck = class {
959
+ static {
960
+ __name(this, "UserPortDoctorCheck");
961
+ }
962
+ users;
963
+ id = "platform.user-port";
964
+ label = "UserPort.findByEmail erreichbar";
965
+ constructor(users) {
966
+ this.users = users;
967
+ }
968
+ async run() {
969
+ try {
970
+ await this.users.findByEmail("__doctor-check__@invalid.local");
971
+ return {
972
+ severity: "ok",
973
+ message: "UserPort antwortet."
974
+ };
975
+ } catch (err2) {
976
+ return {
977
+ severity: "error",
978
+ message: `UserPort wirft: ${err2 instanceof Error ? err2.message : String(err2)}`
979
+ };
980
+ }
981
+ }
982
+ };
983
+ UserPortDoctorCheck = _ts_decorate7([
984
+ Injectable7(),
985
+ _ts_param6(0, Inject6(USER_PORT_TOKEN)),
986
+ _ts_metadata7("design:type", Function),
987
+ _ts_metadata7("design:paramtypes", [
988
+ typeof UserPort === "undefined" ? Object : UserPort
989
+ ])
990
+ ], UserPortDoctorCheck);
991
+ var AdminManifestDoctorCheck = class {
992
+ static {
993
+ __name(this, "AdminManifestDoctorCheck");
994
+ }
995
+ manifest;
996
+ id = "platform.admin-manifest";
997
+ label = "AdminManifestService liefert Manifest";
998
+ constructor(manifest) {
999
+ this.manifest = manifest;
1000
+ }
1001
+ async run() {
1002
+ try {
1003
+ const m = this.manifest.getManifest();
1004
+ const pageCount = Object.keys(m.navigation?.standardPages ?? {}).length;
1005
+ return {
1006
+ severity: "ok",
1007
+ message: `Manifest mit ${pageCount} Standard-Pages, Hash ${m.build?.manifestHash?.slice(0, 12) ?? "???"}\u2026`
1008
+ };
1009
+ } catch (err2) {
1010
+ return {
1011
+ severity: "error",
1012
+ message: `Manifest-Build wirft: ${err2 instanceof Error ? err2.message : String(err2)}`
1013
+ };
1014
+ }
1015
+ }
1016
+ };
1017
+ AdminManifestDoctorCheck = _ts_decorate7([
1018
+ Injectable7(),
1019
+ _ts_metadata7("design:type", Function),
1020
+ _ts_metadata7("design:paramtypes", [
1021
+ typeof AdminManifestService === "undefined" ? Object : AdminManifestService
1022
+ ])
1023
+ ], AdminManifestDoctorCheck);
1024
+ var PLATFORM_DOCTOR_CHECK_PROVIDERS = [
1025
+ PlanCatalogDoctorCheck,
1026
+ DiscoverySnapshotDoctorCheck,
1027
+ UserPortDoctorCheck,
1028
+ AdminManifestDoctorCheck
1029
+ ];
1030
+
1031
+ // src/schema-apply.ts
1032
+ function stripLineComment(line) {
1033
+ const commentStart = line.indexOf("//");
1034
+ return commentStart === -1 ? line : line.slice(0, commentStart);
1035
+ }
1036
+ __name(stripLineComment, "stripLineComment");
1037
+ function extractModelNames(schema) {
1038
+ const names = [];
1039
+ const lines = schema.split("\n");
1040
+ for (const line of lines) {
1041
+ const stripped = stripLineComment(line).trim();
1042
+ const match = stripped.match(/^model\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/);
1043
+ if (match) names.push(match[1]);
1044
+ }
1045
+ return names;
1046
+ }
1047
+ __name(extractModelNames, "extractModelNames");
1048
+ function extractModelBlocks(fragment) {
1049
+ const blocks = /* @__PURE__ */ new Map();
1050
+ const lines = fragment.split("\n");
1051
+ let current = null;
1052
+ for (const rawLine of lines) {
1053
+ const stripped = stripLineComment(rawLine);
1054
+ if (!current) {
1055
+ const match = rawLine.match(/^\s*model\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/);
1056
+ if (match) {
1057
+ const openCount = (stripped.match(/\{/g) ?? []).length;
1058
+ const closeCount = (stripped.match(/\}/g) ?? []).length;
1059
+ current = {
1060
+ name: match[1],
1061
+ lines: [
1062
+ rawLine
1063
+ ],
1064
+ depth: openCount - closeCount
1065
+ };
1066
+ if (current.depth === 0) {
1067
+ blocks.set(current.name, current.lines.join("\n"));
1068
+ current = null;
1069
+ }
1070
+ }
1071
+ continue;
1072
+ }
1073
+ current.lines.push(rawLine);
1074
+ current.depth += (stripped.match(/\{/g) ?? []).length;
1075
+ current.depth -= (stripped.match(/\}/g) ?? []).length;
1076
+ if (current.depth <= 0) {
1077
+ blocks.set(current.name, current.lines.join("\n"));
1078
+ current = null;
1079
+ }
1080
+ }
1081
+ return blocks;
1082
+ }
1083
+ __name(extractModelBlocks, "extractModelBlocks");
1084
+ function applyFragmentBlocks(schema, fragmentBlocks, options = {}) {
1085
+ const existing = new Set(extractModelNames(schema));
1086
+ const added = [];
1087
+ const skipped = [];
1088
+ const additions = [];
1089
+ for (const [name, block] of fragmentBlocks) {
1090
+ if (existing.has(name)) {
1091
+ skipped.push(name);
1092
+ } else {
1093
+ added.push(name);
1094
+ additions.push(block);
1095
+ }
1096
+ }
1097
+ if (additions.length === 0) {
1098
+ return {
1099
+ added,
1100
+ skipped,
1101
+ schema
1102
+ };
1103
+ }
1104
+ const header = options.fragmentLabel ? `
1105
+
1106
+ // ============================================================
1107
+ // Eingef\xFCgt durch \`saas-platform schema apply\` aus ${options.fragmentLabel}
1108
+ // ============================================================
1109
+ ` : `
1110
+
1111
+ // Eingef\xFCgt durch \`saas-platform schema apply\`
1112
+ `;
1113
+ const trimmedSchema = schema.endsWith("\n") ? schema : schema + "\n";
1114
+ return {
1115
+ added,
1116
+ skipped,
1117
+ schema: trimmedSchema + header + additions.join("\n\n") + "\n"
1118
+ };
1119
+ }
1120
+ __name(applyFragmentBlocks, "applyFragmentBlocks");
1121
+
1122
+ // src/module.ts
1123
+ import { Module } from "@nestjs/common";
1124
+ import { asProvider } from "@saasicat/nest";
1125
+ function _ts_decorate8(decorators, target, key, desc) {
1126
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1127
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1128
+ 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;
1129
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1130
+ }
1131
+ __name(_ts_decorate8, "_ts_decorate");
1132
+ var CliContextModule = class _CliContextModule {
1133
+ static {
1134
+ __name(this, "CliContextModule");
1135
+ }
1136
+ static forRoot(options) {
1137
+ const providers = [
1138
+ {
1139
+ provide: CLI_CONTEXT_CONFIG_TOKEN,
1140
+ useValue: options.config
1141
+ },
1142
+ asProvider(USER_PORT_TOKEN, options.userPort),
1143
+ CliContextService,
1144
+ MfaSetupFlow,
1145
+ WhoAmIFlow
1146
+ ];
1147
+ const exports_ = [
1148
+ CLI_CONTEXT_CONFIG_TOKEN,
1149
+ CliContextService,
1150
+ MfaSetupFlow,
1151
+ WhoAmIFlow
1152
+ ];
1153
+ if (options.auditQueryPort) {
1154
+ providers.push(asProvider(AUDIT_QUERY_PORT_TOKEN, options.auditQueryPort));
1155
+ providers.push(AuditTailFlow);
1156
+ exports_.push(AuditTailFlow);
1157
+ }
1158
+ if (options.defaultDoctorChecks) {
1159
+ providers.push(...PLATFORM_DOCTOR_CHECK_PROVIDERS);
1160
+ providers.push({
1161
+ provide: DOCTOR_CHECKS_TOKEN,
1162
+ useFactory: /* @__PURE__ */ __name((...platformChecks) => {
1163
+ const extra = Array.isArray(options.doctorChecks) ? options.doctorChecks : [];
1164
+ return [
1165
+ ...platformChecks,
1166
+ ...extra
1167
+ ];
1168
+ }, "useFactory"),
1169
+ inject: PLATFORM_DOCTOR_CHECK_PROVIDERS
1170
+ });
1171
+ } else {
1172
+ providers.push(asProvider(DOCTOR_CHECKS_TOKEN, options.doctorChecks ?? []));
1173
+ }
1174
+ providers.push(DoctorFlow);
1175
+ exports_.push(DoctorFlow);
1176
+ if (options.manifestAccessPort) {
1177
+ providers.push(asProvider(MANIFEST_ACCESS_PORT_TOKEN, options.manifestAccessPort), asProvider(MANIFEST_CHECKS_TOKEN, options.manifestChecks ?? DEFAULT_MANIFEST_CHECKS), ManifestCliFlow);
1178
+ exports_.push(ManifestCliFlow);
1179
+ }
1180
+ if (options.userManagementPort) {
1181
+ providers.push(asProvider(USER_MANAGEMENT_PORT_TOKEN, options.userManagementPort));
1182
+ exports_.push(USER_MANAGEMENT_PORT_TOKEN);
1183
+ }
1184
+ return {
1185
+ module: _CliContextModule,
1186
+ global: options.global ?? false,
1187
+ providers,
1188
+ exports: exports_
1189
+ };
1190
+ }
1191
+ };
1192
+ CliContextModule = _ts_decorate8([
1193
+ Module({})
1194
+ ], CliContextModule);
1195
+
1196
+ // src/manifest.command.ts
1197
+ import { Injectable as Injectable8 } from "@nestjs/common";
1198
+ import { Command, CommandRunner, Option, SubCommand } from "nest-commander";
1199
+ function _ts_decorate9(decorators, target, key, desc) {
1200
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1201
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1202
+ 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;
1203
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1204
+ }
1205
+ __name(_ts_decorate9, "_ts_decorate");
1206
+ function _ts_metadata8(k, v) {
1207
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1208
+ }
1209
+ __name(_ts_metadata8, "_ts_metadata");
1210
+ var ManifestDumpCommand = class extends CommandRunner {
1211
+ static {
1212
+ __name(this, "ManifestDumpCommand");
1213
+ }
1214
+ ctx;
1215
+ flow;
1216
+ constructor(ctx, flow) {
1217
+ super(), this.ctx = ctx, this.flow = flow;
1218
+ }
1219
+ async run(_args, flags) {
1220
+ const identity = this.ctx.resolveIdentity(flags.as);
1221
+ await this.ctx.ensureSuperAdmin(identity);
1222
+ process.stdout.write(JSON.stringify(this.flow.dump(), null, 2) + "\n");
1223
+ }
1224
+ parseAs(v) {
1225
+ return v;
1226
+ }
1227
+ };
1228
+ _ts_decorate9([
1229
+ Option({
1230
+ flags: "--as <email>"
1231
+ }),
1232
+ _ts_metadata8("design:type", Function),
1233
+ _ts_metadata8("design:paramtypes", [
1234
+ String
1235
+ ]),
1236
+ _ts_metadata8("design:returntype", String)
1237
+ ], ManifestDumpCommand.prototype, "parseAs", null);
1238
+ ManifestDumpCommand = _ts_decorate9([
1239
+ Injectable8(),
1240
+ SubCommand({
1241
+ name: "dump",
1242
+ description: "Manifest als JSON ausgeben"
1243
+ }),
1244
+ _ts_metadata8("design:type", Function),
1245
+ _ts_metadata8("design:paramtypes", [
1246
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1247
+ typeof ManifestCliFlow === "undefined" ? Object : ManifestCliFlow
1248
+ ])
1249
+ ], ManifestDumpCommand);
1250
+ var ManifestHashCommand = class extends CommandRunner {
1251
+ static {
1252
+ __name(this, "ManifestHashCommand");
1253
+ }
1254
+ ctx;
1255
+ flow;
1256
+ constructor(ctx, flow) {
1257
+ super(), this.ctx = ctx, this.flow = flow;
1258
+ }
1259
+ async run(_args, flags) {
1260
+ const identity = this.ctx.resolveIdentity(flags.as);
1261
+ await this.ctx.ensureSuperAdmin(identity);
1262
+ process.stdout.write(this.flow.hash() + "\n");
1263
+ }
1264
+ parseAs(v) {
1265
+ return v;
1266
+ }
1267
+ };
1268
+ _ts_decorate9([
1269
+ Option({
1270
+ flags: "--as <email>"
1271
+ }),
1272
+ _ts_metadata8("design:type", Function),
1273
+ _ts_metadata8("design:paramtypes", [
1274
+ String
1275
+ ]),
1276
+ _ts_metadata8("design:returntype", String)
1277
+ ], ManifestHashCommand.prototype, "parseAs", null);
1278
+ ManifestHashCommand = _ts_decorate9([
1279
+ Injectable8(),
1280
+ SubCommand({
1281
+ name: "hash",
1282
+ description: "manifestHash ausgeben (CI-Pinning)"
1283
+ }),
1284
+ _ts_metadata8("design:type", Function),
1285
+ _ts_metadata8("design:paramtypes", [
1286
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1287
+ typeof ManifestCliFlow === "undefined" ? Object : ManifestCliFlow
1288
+ ])
1289
+ ], ManifestHashCommand);
1290
+ var ManifestValidateCommand = class extends CommandRunner {
1291
+ static {
1292
+ __name(this, "ManifestValidateCommand");
1293
+ }
1294
+ ctx;
1295
+ flow;
1296
+ constructor(ctx, flow) {
1297
+ super(), this.ctx = ctx, this.flow = flow;
1298
+ }
1299
+ async run(_args, flags) {
1300
+ const identity = this.ctx.resolveIdentity(flags.as);
1301
+ await this.ctx.ensureSuperAdmin(identity);
1302
+ const result = this.flow.validate();
1303
+ if (result.ok) {
1304
+ process.stdout.write("Manifest validiert \u2713\n");
1305
+ return;
1306
+ }
1307
+ process.stderr.write(`Manifest invalid: ${result.reason}
1308
+ `);
1309
+ process.exit(1);
1310
+ }
1311
+ parseAs(v) {
1312
+ return v;
1313
+ }
1314
+ };
1315
+ _ts_decorate9([
1316
+ Option({
1317
+ flags: "--as <email>"
1318
+ }),
1319
+ _ts_metadata8("design:type", Function),
1320
+ _ts_metadata8("design:paramtypes", [
1321
+ String
1322
+ ]),
1323
+ _ts_metadata8("design:returntype", String)
1324
+ ], ManifestValidateCommand.prototype, "parseAs", null);
1325
+ ManifestValidateCommand = _ts_decorate9([
1326
+ Injectable8(),
1327
+ SubCommand({
1328
+ name: "validate",
1329
+ description: "Schnell-Sanity (schemaVersion + project.key + manifestHash)"
1330
+ }),
1331
+ _ts_metadata8("design:type", Function),
1332
+ _ts_metadata8("design:paramtypes", [
1333
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1334
+ typeof ManifestCliFlow === "undefined" ? Object : ManifestCliFlow
1335
+ ])
1336
+ ], ManifestValidateCommand);
1337
+ var ManifestCheckCommand = class extends CommandRunner {
1338
+ static {
1339
+ __name(this, "ManifestCheckCommand");
1340
+ }
1341
+ ctx;
1342
+ flow;
1343
+ constructor(ctx, flow) {
1344
+ super(), this.ctx = ctx, this.flow = flow;
1345
+ }
1346
+ async run(_args, flags) {
1347
+ const identity = this.ctx.resolveIdentity(flags.as);
1348
+ await this.ctx.ensureSuperAdmin(identity);
1349
+ const report = await this.flow.runChecks();
1350
+ process.stdout.write(this.flow.formatReport(report) + "\n");
1351
+ const code = this.flow.exitCodeFor(report);
1352
+ if (code !== 0) process.exit(code);
1353
+ }
1354
+ parseAs(v) {
1355
+ return v;
1356
+ }
1357
+ };
1358
+ _ts_decorate9([
1359
+ Option({
1360
+ flags: "--as <email>"
1361
+ }),
1362
+ _ts_metadata8("design:type", Function),
1363
+ _ts_metadata8("design:paramtypes", [
1364
+ String
1365
+ ]),
1366
+ _ts_metadata8("design:returntype", String)
1367
+ ], ManifestCheckCommand.prototype, "parseAs", null);
1368
+ ManifestCheckCommand = _ts_decorate9([
1369
+ Injectable8(),
1370
+ SubCommand({
1371
+ name: "check",
1372
+ description: "Alle Manifest-Checks (Exit-Code 7 bei error/Drift)"
1373
+ }),
1374
+ _ts_metadata8("design:type", Function),
1375
+ _ts_metadata8("design:paramtypes", [
1376
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1377
+ typeof ManifestCliFlow === "undefined" ? Object : ManifestCliFlow
1378
+ ])
1379
+ ], ManifestCheckCommand);
1380
+ var ManifestCommands = class extends CommandRunner {
1381
+ static {
1382
+ __name(this, "ManifestCommands");
1383
+ }
1384
+ async run() {
1385
+ process.stderr.write("Bitte Sub-Command angeben: dump, hash, validate, check.\n");
1386
+ process.exit(2);
1387
+ }
1388
+ };
1389
+ ManifestCommands = _ts_decorate9([
1390
+ Injectable8(),
1391
+ Command({
1392
+ name: "manifest",
1393
+ description: "Manifest-Operations (dump, hash, validate, check)",
1394
+ subCommands: [
1395
+ ManifestDumpCommand,
1396
+ ManifestHashCommand,
1397
+ ManifestValidateCommand,
1398
+ ManifestCheckCommand
1399
+ ]
1400
+ })
1401
+ ], ManifestCommands);
1402
+
1403
+ // src/admin.command.ts
1404
+ import { Inject as Inject7, Injectable as Injectable9 } from "@nestjs/common";
1405
+ import { Command as Command2, CommandRunner as CommandRunner2, Option as Option2, SubCommand as SubCommand2 } from "nest-commander";
1406
+ import qrcodeTerminal from "qrcode-terminal";
1407
+ function _ts_decorate10(decorators, target, key, desc) {
1408
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1409
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1410
+ 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;
1411
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1412
+ }
1413
+ __name(_ts_decorate10, "_ts_decorate");
1414
+ function _ts_metadata9(k, v) {
1415
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1416
+ }
1417
+ __name(_ts_metadata9, "_ts_metadata");
1418
+ function _ts_param7(paramIndex, decorator) {
1419
+ return function(target, key) {
1420
+ decorator(target, key, paramIndex);
1421
+ };
1422
+ }
1423
+ __name(_ts_param7, "_ts_param");
1424
+ var AdminWhoamiCommand = class extends CommandRunner2 {
1425
+ static {
1426
+ __name(this, "AdminWhoamiCommand");
1427
+ }
1428
+ flow;
1429
+ constructor(flow) {
1430
+ super(), this.flow = flow;
1431
+ }
1432
+ async run(_args, flags) {
1433
+ const result = await this.flow.run(flags.as);
1434
+ process.stdout.write(this.flow.formatResult(result) + "\n");
1435
+ }
1436
+ parseAs(v) {
1437
+ return v;
1438
+ }
1439
+ };
1440
+ _ts_decorate10([
1441
+ Option2({
1442
+ flags: "--as <email>"
1443
+ }),
1444
+ _ts_metadata9("design:type", Function),
1445
+ _ts_metadata9("design:paramtypes", [
1446
+ String
1447
+ ]),
1448
+ _ts_metadata9("design:returntype", String)
1449
+ ], AdminWhoamiCommand.prototype, "parseAs", null);
1450
+ AdminWhoamiCommand = _ts_decorate10([
1451
+ Injectable9(),
1452
+ SubCommand2({
1453
+ name: "whoami",
1454
+ description: "Aktive CLI-Identit\xE4t + MFA-/Production-Status"
1455
+ }),
1456
+ _ts_metadata9("design:type", Function),
1457
+ _ts_metadata9("design:paramtypes", [
1458
+ typeof WhoAmIFlow === "undefined" ? Object : WhoAmIFlow
1459
+ ])
1460
+ ], AdminWhoamiCommand);
1461
+ var AdminMfaSetupCommand = class extends CommandRunner2 {
1462
+ static {
1463
+ __name(this, "AdminMfaSetupCommand");
1464
+ }
1465
+ config;
1466
+ flow;
1467
+ constructor(config, flow) {
1468
+ super(), this.config = config, this.flow = flow;
1469
+ }
1470
+ async run(_args, flags) {
1471
+ const result = await this.flow.run({
1472
+ asFlag: flags.as,
1473
+ issuer: this.config.mfaIssuer ?? "SuperAdmin",
1474
+ force: flags.force
1475
+ });
1476
+ await new Promise((resolve) => {
1477
+ qrcodeTerminal.generate(result.otpauthUri, {
1478
+ small: true
1479
+ }, (qr) => {
1480
+ process.stdout.write("\n" + qr + "\n");
1481
+ resolve();
1482
+ });
1483
+ });
1484
+ process.stdout.write(this.flow.formatSetupResult(result) + "\n");
1485
+ }
1486
+ parseAs(v) {
1487
+ return v;
1488
+ }
1489
+ parseForce() {
1490
+ return true;
1491
+ }
1492
+ };
1493
+ _ts_decorate10([
1494
+ Option2({
1495
+ flags: "--as <email>"
1496
+ }),
1497
+ _ts_metadata9("design:type", Function),
1498
+ _ts_metadata9("design:paramtypes", [
1499
+ String
1500
+ ]),
1501
+ _ts_metadata9("design:returntype", String)
1502
+ ], AdminMfaSetupCommand.prototype, "parseAs", null);
1503
+ _ts_decorate10([
1504
+ Option2({
1505
+ flags: "--force",
1506
+ description: "bestehendes Secret ohne R\xFCckfrage \xFCberschreiben"
1507
+ }),
1508
+ _ts_metadata9("design:type", Function),
1509
+ _ts_metadata9("design:paramtypes", []),
1510
+ _ts_metadata9("design:returntype", Boolean)
1511
+ ], AdminMfaSetupCommand.prototype, "parseForce", null);
1512
+ AdminMfaSetupCommand = _ts_decorate10([
1513
+ Injectable9(),
1514
+ SubCommand2({
1515
+ name: "mfa-setup",
1516
+ description: "TOTP-MFA f\xFCr den eigenen SuperAdmin einrichten"
1517
+ }),
1518
+ _ts_param7(0, Inject7(CLI_CONTEXT_CONFIG_TOKEN)),
1519
+ _ts_metadata9("design:type", Function),
1520
+ _ts_metadata9("design:paramtypes", [
1521
+ typeof CliContextConfig === "undefined" ? Object : CliContextConfig,
1522
+ typeof MfaSetupFlow === "undefined" ? Object : MfaSetupFlow
1523
+ ])
1524
+ ], AdminMfaSetupCommand);
1525
+ var AdminCommands = class extends CommandRunner2 {
1526
+ static {
1527
+ __name(this, "AdminCommands");
1528
+ }
1529
+ async run() {
1530
+ process.stderr.write("Bitte Sub-Command angeben: whoami, mfa-setup.\n");
1531
+ process.exit(2);
1532
+ }
1533
+ };
1534
+ AdminCommands = _ts_decorate10([
1535
+ Injectable9(),
1536
+ Command2({
1537
+ name: "admin",
1538
+ description: "SuperAdmin-Operations (whoami, mfa-setup)",
1539
+ subCommands: [
1540
+ AdminWhoamiCommand,
1541
+ AdminMfaSetupCommand
1542
+ ]
1543
+ })
1544
+ ], AdminCommands);
1545
+
1546
+ // src/audit.command.ts
1547
+ import { Injectable as Injectable10 } from "@nestjs/common";
1548
+ import { Command as Command3, CommandRunner as CommandRunner3, Option as Option3, SubCommand as SubCommand3 } from "nest-commander";
1549
+ function _ts_decorate11(decorators, target, key, desc) {
1550
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1551
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1552
+ 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;
1553
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1554
+ }
1555
+ __name(_ts_decorate11, "_ts_decorate");
1556
+ function _ts_metadata10(k, v) {
1557
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1558
+ }
1559
+ __name(_ts_metadata10, "_ts_metadata");
1560
+ var AuditTailCommand = class extends CommandRunner3 {
1561
+ static {
1562
+ __name(this, "AuditTailCommand");
1563
+ }
1564
+ ctx;
1565
+ flow;
1566
+ constructor(ctx, flow) {
1567
+ super(), this.ctx = ctx, this.flow = flow;
1568
+ }
1569
+ async run(_args, flags) {
1570
+ const identity = this.ctx.resolveIdentity(flags.as);
1571
+ await this.ctx.ensureSuperAdmin(identity);
1572
+ const entries = await this.flow.run({
1573
+ actor: flags.actor,
1574
+ action: flags.action,
1575
+ entity: flags.entity,
1576
+ since: flags.since,
1577
+ limit: flags.limit
1578
+ });
1579
+ this.ctx.table(this.flow.formatRows(entries));
1580
+ }
1581
+ parseAs(v) {
1582
+ return v;
1583
+ }
1584
+ parseActor(v) {
1585
+ return v;
1586
+ }
1587
+ parseAction(v) {
1588
+ return v;
1589
+ }
1590
+ parseEntity(v) {
1591
+ return v;
1592
+ }
1593
+ parseSince(v) {
1594
+ return v;
1595
+ }
1596
+ parseLimit(v) {
1597
+ return Number.parseInt(v, 10);
1598
+ }
1599
+ };
1600
+ _ts_decorate11([
1601
+ Option3({
1602
+ flags: "--as <email>"
1603
+ }),
1604
+ _ts_metadata10("design:type", Function),
1605
+ _ts_metadata10("design:paramtypes", [
1606
+ String
1607
+ ]),
1608
+ _ts_metadata10("design:returntype", String)
1609
+ ], AuditTailCommand.prototype, "parseAs", null);
1610
+ _ts_decorate11([
1611
+ Option3({
1612
+ flags: "--actor <email>"
1613
+ }),
1614
+ _ts_metadata10("design:type", Function),
1615
+ _ts_metadata10("design:paramtypes", [
1616
+ String
1617
+ ]),
1618
+ _ts_metadata10("design:returntype", String)
1619
+ ], AuditTailCommand.prototype, "parseActor", null);
1620
+ _ts_decorate11([
1621
+ Option3({
1622
+ flags: "--action <name>"
1623
+ }),
1624
+ _ts_metadata10("design:type", Function),
1625
+ _ts_metadata10("design:paramtypes", [
1626
+ String
1627
+ ]),
1628
+ _ts_metadata10("design:returntype", String)
1629
+ ], AuditTailCommand.prototype, "parseAction", null);
1630
+ _ts_decorate11([
1631
+ Option3({
1632
+ flags: "--entity <name>"
1633
+ }),
1634
+ _ts_metadata10("design:type", Function),
1635
+ _ts_metadata10("design:paramtypes", [
1636
+ String
1637
+ ]),
1638
+ _ts_metadata10("design:returntype", String)
1639
+ ], AuditTailCommand.prototype, "parseEntity", null);
1640
+ _ts_decorate11([
1641
+ Option3({
1642
+ flags: "--since <iso-date>"
1643
+ }),
1644
+ _ts_metadata10("design:type", Function),
1645
+ _ts_metadata10("design:paramtypes", [
1646
+ String
1647
+ ]),
1648
+ _ts_metadata10("design:returntype", String)
1649
+ ], AuditTailCommand.prototype, "parseSince", null);
1650
+ _ts_decorate11([
1651
+ Option3({
1652
+ flags: "--limit <n>"
1653
+ }),
1654
+ _ts_metadata10("design:type", Function),
1655
+ _ts_metadata10("design:paramtypes", [
1656
+ String
1657
+ ]),
1658
+ _ts_metadata10("design:returntype", Number)
1659
+ ], AuditTailCommand.prototype, "parseLimit", null);
1660
+ AuditTailCommand = _ts_decorate11([
1661
+ Injectable10(),
1662
+ SubCommand3({
1663
+ name: "tail",
1664
+ description: "Letzte Audit-Log-Eintr\xE4ge (--actor/--action/--entity/--since/--limit)"
1665
+ }),
1666
+ _ts_metadata10("design:type", Function),
1667
+ _ts_metadata10("design:paramtypes", [
1668
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1669
+ typeof AuditTailFlow === "undefined" ? Object : AuditTailFlow
1670
+ ])
1671
+ ], AuditTailCommand);
1672
+ var AuditCommands = class extends CommandRunner3 {
1673
+ static {
1674
+ __name(this, "AuditCommands");
1675
+ }
1676
+ async run() {
1677
+ process.stderr.write("Bitte Sub-Command angeben: tail.\n");
1678
+ process.exit(2);
1679
+ }
1680
+ };
1681
+ AuditCommands = _ts_decorate11([
1682
+ Injectable10(),
1683
+ Command3({
1684
+ name: "audit",
1685
+ description: "Audit-Log-Operations (tail)",
1686
+ subCommands: [
1687
+ AuditTailCommand
1688
+ ]
1689
+ })
1690
+ ], AuditCommands);
1691
+
1692
+ // src/doctor.command.ts
1693
+ import { Injectable as Injectable11 } from "@nestjs/common";
1694
+ import { Command as Command4, CommandRunner as CommandRunner4, Option as Option4 } from "nest-commander";
1695
+ function _ts_decorate12(decorators, target, key, desc) {
1696
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1697
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1698
+ 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;
1699
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1700
+ }
1701
+ __name(_ts_decorate12, "_ts_decorate");
1702
+ function _ts_metadata11(k, v) {
1703
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1704
+ }
1705
+ __name(_ts_metadata11, "_ts_metadata");
1706
+ var DoctorCommands = class extends CommandRunner4 {
1707
+ static {
1708
+ __name(this, "DoctorCommands");
1709
+ }
1710
+ ctx;
1711
+ flow;
1712
+ constructor(ctx, flow) {
1713
+ super(), this.ctx = ctx, this.flow = flow;
1714
+ }
1715
+ async run(_args, flags) {
1716
+ const identity = this.ctx.resolveIdentity(flags.as);
1717
+ await this.ctx.ensureSuperAdmin(identity);
1718
+ const report = await this.flow.run();
1719
+ process.stdout.write(this.flow.formatReport(report) + "\n");
1720
+ const code = this.flow.exitCodeFor(report);
1721
+ if (code !== 0) process.exit(code);
1722
+ }
1723
+ parseAs(v) {
1724
+ return v;
1725
+ }
1726
+ };
1727
+ _ts_decorate12([
1728
+ Option4({
1729
+ flags: "--as <email>"
1730
+ }),
1731
+ _ts_metadata11("design:type", Function),
1732
+ _ts_metadata11("design:paramtypes", [
1733
+ String
1734
+ ]),
1735
+ _ts_metadata11("design:returntype", String)
1736
+ ], DoctorCommands.prototype, "parseAs", null);
1737
+ DoctorCommands = _ts_decorate12([
1738
+ Injectable11(),
1739
+ Command4({
1740
+ name: "doctor",
1741
+ description: "Health-/Drift-Checks (Exit-Code 4 bei error)"
1742
+ }),
1743
+ _ts_metadata11("design:type", Function),
1744
+ _ts_metadata11("design:paramtypes", [
1745
+ typeof CliContextService === "undefined" ? Object : CliContextService,
1746
+ typeof DoctorFlow === "undefined" ? Object : DoctorFlow
1747
+ ])
1748
+ ], DoctorCommands);
1749
+
1750
+ // src/discovery.command.ts
1751
+ import { mkdirSync, writeFileSync } from "fs";
1752
+ import { dirname, resolve as resolvePath } from "path";
1753
+ import { Inject as Inject8, Injectable as Injectable12, Optional } from "@nestjs/common";
1754
+ import { Command as Command5, CommandRunner as CommandRunner5, Option as Option5, SubCommand as SubCommand4 } from "nest-commander";
1755
+ import { DISCOVERY_SNAPSHOT_PATH_TOKEN, DiscoveryScanner } from "@saasicat/nest";
1756
+ function _ts_decorate13(decorators, target, key, desc) {
1757
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1758
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1759
+ 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;
1760
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1761
+ }
1762
+ __name(_ts_decorate13, "_ts_decorate");
1763
+ function _ts_metadata12(k, v) {
1764
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1765
+ }
1766
+ __name(_ts_metadata12, "_ts_metadata");
1767
+ function _ts_param8(paramIndex, decorator) {
1768
+ return function(target, key) {
1769
+ decorator(target, key, paramIndex);
1770
+ };
1771
+ }
1772
+ __name(_ts_param8, "_ts_param");
1773
+ var DiscoveryScanCommand = class extends CommandRunner5 {
1774
+ static {
1775
+ __name(this, "DiscoveryScanCommand");
1776
+ }
1777
+ scanner;
1778
+ configuredPath;
1779
+ constructor(scanner = null, configuredPath = null) {
1780
+ super(), this.scanner = scanner, this.configuredPath = configuredPath;
1781
+ }
1782
+ async run(_args, flags) {
1783
+ if (!this.scanner) {
1784
+ this.fail("DiscoveryScanner nicht registriert \u2014 DiscoveryModule.forRoot() im CLI-Modul importieren.", flags);
1785
+ return;
1786
+ }
1787
+ try {
1788
+ const snapshot = this.scanner.rebuildSnapshot();
1789
+ if (flags.out) {
1790
+ const outPath = resolvePath(flags.out);
1791
+ mkdirSync(dirname(outPath), {
1792
+ recursive: true
1793
+ });
1794
+ writeFileSync(outPath, JSON.stringify(snapshot, null, 2) + "\n", "utf-8");
1795
+ }
1796
+ const target = flags.out ?? this.configuredPath;
1797
+ process.stdout.write(`Discovery-Scan (${snapshot.app.key} v${snapshot.app.version}): ${snapshot.capabilities.length} Capabilities \xB7 ${snapshot.features.length} Features \xB7 ${snapshot.quotas.length} Quotas \xB7 hash ${snapshot.hash.slice(0, 19)}\u2026
1798
+ `);
1799
+ if (target) {
1800
+ process.stdout.write(`Snapshot persistiert: ${resolvePath(target)}
1801
+ `);
1802
+ } else {
1803
+ process.stderr.write("WARNUNG: Snapshot wurde nicht persistiert \u2014 weder snapshotPath (DiscoveryModule.forRoot) konfiguriert noch --out angegeben. Das Seed-Gate findet so keinen Snapshot.\n");
1804
+ }
1805
+ } catch (err2) {
1806
+ this.fail(err2 instanceof Error ? err2.message : String(err2), flags);
1807
+ }
1808
+ }
1809
+ /** Exit 4 (analogous to Seed-Gate/Preflight) — only a warning with `--non-fatal`. */
1810
+ fail(message, flags) {
1811
+ if (flags.nonFatal) {
1812
+ process.stderr.write(`[discovery scan] WARN (non-fatal): ${message}
1813
+ `);
1814
+ return;
1815
+ }
1816
+ process.stderr.write(`[discovery scan] FEHLER: ${message}
1817
+ `);
1818
+ process.exit(4);
1819
+ }
1820
+ parseOut(v) {
1821
+ return v;
1822
+ }
1823
+ parseNonFatal() {
1824
+ return true;
1825
+ }
1826
+ };
1827
+ _ts_decorate13([
1828
+ Option5({
1829
+ flags: "--out <path>",
1830
+ description: "Snapshot zus\xE4tzlich an diesen Pfad schreiben"
1831
+ }),
1832
+ _ts_metadata12("design:type", Function),
1833
+ _ts_metadata12("design:paramtypes", [
1834
+ String
1835
+ ]),
1836
+ _ts_metadata12("design:returntype", String)
1837
+ ], DiscoveryScanCommand.prototype, "parseOut", null);
1838
+ _ts_decorate13([
1839
+ Option5({
1840
+ flags: "--non-fatal",
1841
+ description: "Scan-Fehler nur als Warnung melden (Exit 0) \u2014 gestufter Rollout"
1842
+ }),
1843
+ _ts_metadata12("design:type", Function),
1844
+ _ts_metadata12("design:paramtypes", []),
1845
+ _ts_metadata12("design:returntype", Boolean)
1846
+ ], DiscoveryScanCommand.prototype, "parseNonFatal", null);
1847
+ DiscoveryScanCommand = _ts_decorate13([
1848
+ Injectable12(),
1849
+ SubCommand4({
1850
+ name: "scan",
1851
+ description: "Discovery-Snapshot headless erzeugen + persistieren (Seed-Gate, #23)"
1852
+ }),
1853
+ _ts_param8(0, Optional()),
1854
+ _ts_param8(0, Inject8(DiscoveryScanner)),
1855
+ _ts_param8(1, Optional()),
1856
+ _ts_param8(1, Inject8(DISCOVERY_SNAPSHOT_PATH_TOKEN)),
1857
+ _ts_metadata12("design:type", Function),
1858
+ _ts_metadata12("design:paramtypes", [
1859
+ Object,
1860
+ Object
1861
+ ])
1862
+ ], DiscoveryScanCommand);
1863
+ var DiscoveryCommands = class extends CommandRunner5 {
1864
+ static {
1865
+ __name(this, "DiscoveryCommands");
1866
+ }
1867
+ async run() {
1868
+ process.stderr.write("Bitte Sub-Command angeben: scan.\n");
1869
+ process.exit(2);
1870
+ }
1871
+ };
1872
+ DiscoveryCommands = _ts_decorate13([
1873
+ Injectable12(),
1874
+ Command5({
1875
+ name: "discovery",
1876
+ description: "Discovery-Operations (scan)",
1877
+ subCommands: [
1878
+ DiscoveryScanCommand
1879
+ ]
1880
+ })
1881
+ ], DiscoveryCommands);
1882
+
1883
+ // src/user.command.ts
1884
+ import { Inject as Inject9, Injectable as Injectable13 } from "@nestjs/common";
1885
+ import { randomBytes } from "crypto";
1886
+ import { Command as Command6, CommandRunner as CommandRunner6, Option as Option6 } from "nest-commander";
1887
+ function _ts_decorate14(decorators, target, key, desc) {
1888
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1889
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1890
+ 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;
1891
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1892
+ }
1893
+ __name(_ts_decorate14, "_ts_decorate");
1894
+ function _ts_metadata13(k, v) {
1895
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1896
+ }
1897
+ __name(_ts_metadata13, "_ts_metadata");
1898
+ function _ts_param9(paramIndex, decorator) {
1899
+ return function(target, key) {
1900
+ decorator(target, key, paramIndex);
1901
+ };
1902
+ }
1903
+ __name(_ts_param9, "_ts_param");
1904
+ var AUDIT_ENTITY = "User";
1905
+ function generatePassword() {
1906
+ return randomBytes(12).toString("base64url");
1907
+ }
1908
+ __name(generatePassword, "generatePassword");
1909
+ var UserCommands = class extends CommandRunner6 {
1910
+ static {
1911
+ __name(this, "UserCommands");
1912
+ }
1913
+ ctx;
1914
+ users;
1915
+ constructor(ctx, users) {
1916
+ super(), this.ctx = ctx, this.users = users;
1917
+ }
1918
+ async run(args, flags) {
1919
+ const sub = args[0];
1920
+ const identity = this.ctx.resolveIdentity(flags.as);
1921
+ const me = await this.ctx.ensureSuperAdmin(identity);
1922
+ switch (sub) {
1923
+ case "create-super-admin":
1924
+ return this.createSuperAdmin(args[1], flags, identity, me.id, me.email);
1925
+ case "reassign-admin":
1926
+ return this.reassignAdmin(args[1], flags, identity, me.id);
1927
+ case "list":
1928
+ return this.list(args[1]);
1929
+ case "reset-password":
1930
+ return this.resetPassword(args[1], flags, identity, me.id);
1931
+ case "deactivate":
1932
+ return this.deactivate(args[1], flags, identity, me.id);
1933
+ default:
1934
+ throw new CliError("UNKNOWN_SUBCOMMAND", `Unbekannter Subbefehl: user ${sub ?? "(leer)"}. Verf\xFCgbar: create-super-admin <email>, reassign-admin <slug>, list <slug>, reset-password <email>, deactivate <email>.`, 1);
1935
+ }
1936
+ }
1937
+ async createSuperAdmin(email, flags, identity, meId, meEmail) {
1938
+ if (!email) {
1939
+ throw new CliError("MISSING_ARG", "user create-super-admin <email> erwartet eine E-Mail.", 1);
1940
+ }
1941
+ await this.ctx.requireMfa(meId);
1942
+ await this.ctx.ensureProductionConfirmation({
1943
+ yes: flags.yes
1944
+ });
1945
+ const generated = !flags.password;
1946
+ const password = flags.password ?? generatePassword();
1947
+ const created = await this.users.createSuperAdmin({
1948
+ email: email.toLowerCase(),
1949
+ password,
1950
+ firstName: flags.first,
1951
+ lastName: flags.last
1952
+ });
1953
+ await this.ctx.log({
1954
+ identity,
1955
+ userId: meId,
1956
+ entity: AUDIT_ENTITY,
1957
+ entityId: created.id,
1958
+ action: "SUPER_ADMIN_CREATE",
1959
+ changes: {
1960
+ email: created.email,
1961
+ createdBy: meEmail
1962
+ }
1963
+ });
1964
+ console.log(`\u2714 SUPER_ADMIN ${created.email} angelegt (durch ${meEmail}).`);
1965
+ console.log(` User-ID: ${created.id}`);
1966
+ if (generated) {
1967
+ console.log(` Passwort: ${password}`);
1968
+ console.log(" \u2192 Sicher \xFCbermitteln. Beim ersten Login \xE4ndern.");
1969
+ }
1970
+ console.log(` N\xE4chster Schritt: admin mfa-setup f\xFCr ${created.email}.`);
1971
+ }
1972
+ async reassignAdmin(slug, flags, identity, meId) {
1973
+ if (!slug) {
1974
+ throw new CliError("MISSING_ARG", "user reassign-admin <tenant-slug> erwartet einen Slug.", 1);
1975
+ }
1976
+ if (!flags.to) throw new CliError("MISSING_FLAG", "--to=<email> ist Pflicht.", 1);
1977
+ if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" ist Pflicht.', 1);
1978
+ await this.ctx.requireMfa(meId);
1979
+ const result = await this.users.reassignTenantAdmin(slug, flags.to.toLowerCase());
1980
+ await this.ctx.log({
1981
+ identity,
1982
+ userId: meId,
1983
+ entity: AUDIT_ENTITY,
1984
+ entityId: result.user.id,
1985
+ action: result.created ? "USER_REASSIGN_ADMIN" : "USER_ROLE_CHANGE",
1986
+ changes: {
1987
+ tenant: slug,
1988
+ to: "TENANT_ADMIN",
1989
+ from: result.previousRole,
1990
+ reason: flags.reason,
1991
+ emergency: true
1992
+ }
1993
+ });
1994
+ if (result.created) {
1995
+ console.log(`\u2714 Notfall-Admin ${result.user.email} f\xFCr ${slug} angelegt.`);
1996
+ if (result.oneTimePassword) {
1997
+ console.log(` Initial-Passwort: ${result.oneTimePassword}`);
1998
+ console.log(" \u2192 Sicher \xFCbermitteln. Beim ersten Login \xE4ndern.");
1999
+ }
2000
+ } else {
2001
+ console.log(`\u2714 ${result.user.email} ist jetzt TENANT_ADMIN von ${slug}.`);
2002
+ }
2003
+ }
2004
+ async list(slug) {
2005
+ if (!slug) {
2006
+ throw new CliError("MISSING_ARG", "user list <tenant-slug> erwartet einen Slug.", 1);
2007
+ }
2008
+ const rows = await this.users.listTenantUsers(slug);
2009
+ this.ctx.table(rows.map((u) => ({
2010
+ email: u.email,
2011
+ role: u.role,
2012
+ status: u.status,
2013
+ lastLogin: u.lastLoginAt?.slice(0, 10) ?? "\u2014"
2014
+ })));
2015
+ }
2016
+ async resetPassword(email, flags, identity, meId) {
2017
+ if (!email) {
2018
+ throw new CliError("MISSING_ARG", "user reset-password <email> erwartet eine E-Mail.", 1);
2019
+ }
2020
+ if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" ist Pflicht.', 1);
2021
+ const result = await this.users.triggerPasswordReset(email.toLowerCase());
2022
+ await this.ctx.log({
2023
+ identity,
2024
+ userId: meId,
2025
+ entity: AUDIT_ENTITY,
2026
+ entityId: result.user.id,
2027
+ action: "USER_PASSWORD_RESET_TRIGGERED",
2028
+ changes: {
2029
+ reason: flags.reason
2030
+ }
2031
+ });
2032
+ if (result.oneTimePassword) {
2033
+ console.log(`\u2714 Einmal-Passwort f\xFCr ${result.user.email} gesetzt.`);
2034
+ console.log(` Passwort: ${result.oneTimePassword}`);
2035
+ console.log(" \u2192 Sicher \xFCbermitteln. Beim ersten Login \xE4ndern.");
2036
+ } else {
2037
+ console.log(`\u2714 Passwort-Reset f\xFCr ${result.user.email} ausgel\xF6st.`);
2038
+ }
2039
+ }
2040
+ async deactivate(email, flags, identity, meId) {
2041
+ if (!email) {
2042
+ throw new CliError("MISSING_ARG", "user deactivate <email> erwartet eine E-Mail.", 1);
2043
+ }
2044
+ if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" ist Pflicht.', 1);
2045
+ await this.ctx.requireMfa(meId);
2046
+ await this.ctx.ensureProductionConfirmation({
2047
+ yes: flags.yes
2048
+ });
2049
+ const user = await this.users.deactivate(email.toLowerCase(), flags.reason);
2050
+ await this.ctx.log({
2051
+ identity,
2052
+ userId: meId,
2053
+ entity: AUDIT_ENTITY,
2054
+ entityId: user.id,
2055
+ action: "USER_DEACTIVATED",
2056
+ changes: {
2057
+ reason: flags.reason,
2058
+ emergency: true
2059
+ }
2060
+ });
2061
+ console.log(`\u2714 ${user.email} deaktiviert.`);
2062
+ }
2063
+ parseAs(val) {
2064
+ return val;
2065
+ }
2066
+ parseTo(val) {
2067
+ return val;
2068
+ }
2069
+ parseReason(val) {
2070
+ return val;
2071
+ }
2072
+ parseYes() {
2073
+ return true;
2074
+ }
2075
+ parseFirst(val) {
2076
+ return val;
2077
+ }
2078
+ parseLast(val) {
2079
+ return val;
2080
+ }
2081
+ parsePassword(val) {
2082
+ return val;
2083
+ }
2084
+ };
2085
+ _ts_decorate14([
2086
+ Option6({
2087
+ flags: "--as <email>",
2088
+ description: "CLI-Identit\xE4t (sonst <APP>_ADMIN_EMAIL)"
2089
+ }),
2090
+ _ts_metadata13("design:type", Function),
2091
+ _ts_metadata13("design:paramtypes", [
2092
+ String
2093
+ ]),
2094
+ _ts_metadata13("design:returntype", String)
2095
+ ], UserCommands.prototype, "parseAs", null);
2096
+ _ts_decorate14([
2097
+ Option6({
2098
+ flags: "--to <email>",
2099
+ description: "Ziel-User (reassign-admin)"
2100
+ }),
2101
+ _ts_metadata13("design:type", Function),
2102
+ _ts_metadata13("design:paramtypes", [
2103
+ String
2104
+ ]),
2105
+ _ts_metadata13("design:returntype", String)
2106
+ ], UserCommands.prototype, "parseTo", null);
2107
+ _ts_decorate14([
2108
+ Option6({
2109
+ flags: "--reason <text>",
2110
+ description: "Begr\xFCndung (Audit)"
2111
+ }),
2112
+ _ts_metadata13("design:type", Function),
2113
+ _ts_metadata13("design:paramtypes", [
2114
+ String
2115
+ ]),
2116
+ _ts_metadata13("design:returntype", String)
2117
+ ], UserCommands.prototype, "parseReason", null);
2118
+ _ts_decorate14([
2119
+ Option6({
2120
+ flags: "-y, --yes",
2121
+ description: "Production-Confirmation \xFCberspringen"
2122
+ }),
2123
+ _ts_metadata13("design:type", Function),
2124
+ _ts_metadata13("design:paramtypes", []),
2125
+ _ts_metadata13("design:returntype", Boolean)
2126
+ ], UserCommands.prototype, "parseYes", null);
2127
+ _ts_decorate14([
2128
+ Option6({
2129
+ flags: "--first <name>",
2130
+ description: "Vorname (create-super-admin)"
2131
+ }),
2132
+ _ts_metadata13("design:type", Function),
2133
+ _ts_metadata13("design:paramtypes", [
2134
+ String
2135
+ ]),
2136
+ _ts_metadata13("design:returntype", String)
2137
+ ], UserCommands.prototype, "parseFirst", null);
2138
+ _ts_decorate14([
2139
+ Option6({
2140
+ flags: "--last <name>",
2141
+ description: "Nachname (create-super-admin)"
2142
+ }),
2143
+ _ts_metadata13("design:type", Function),
2144
+ _ts_metadata13("design:paramtypes", [
2145
+ String
2146
+ ]),
2147
+ _ts_metadata13("design:returntype", String)
2148
+ ], UserCommands.prototype, "parseLast", null);
2149
+ _ts_decorate14([
2150
+ Option6({
2151
+ flags: "--password <pwd>",
2152
+ description: "Passwort (create-super-admin; ohne Angabe generiert)"
2153
+ }),
2154
+ _ts_metadata13("design:type", Function),
2155
+ _ts_metadata13("design:paramtypes", [
2156
+ String
2157
+ ]),
2158
+ _ts_metadata13("design:returntype", String)
2159
+ ], UserCommands.prototype, "parsePassword", null);
2160
+ UserCommands = _ts_decorate14([
2161
+ Injectable13(),
2162
+ Command6({
2163
+ name: "user",
2164
+ description: "User-Operationen (create-super-admin, reassign-admin, list, reset-password, deactivate)"
2165
+ }),
2166
+ _ts_param9(1, Inject9(USER_MANAGEMENT_PORT_TOKEN)),
2167
+ _ts_metadata13("design:type", Function),
2168
+ _ts_metadata13("design:paramtypes", [
2169
+ typeof CliContextService === "undefined" ? Object : CliContextService,
2170
+ typeof UserManagementPort === "undefined" ? Object : UserManagementPort
2171
+ ])
2172
+ ], UserCommands);
2173
+ export {
2174
+ AUDIT_QUERY_PORT_TOKEN,
2175
+ AdminCommands,
2176
+ AdminManifestDoctorCheck,
2177
+ AdminMfaSetupCommand,
2178
+ AdminWhoamiCommand,
2179
+ AuditCommands,
2180
+ AuditTailCommand,
2181
+ AuditTailFlow,
2182
+ CLI_CONTEXT_CONFIG_TOKEN,
2183
+ CliContextModule,
2184
+ CliContextService,
2185
+ CliError,
2186
+ DEFAULT_MANIFEST_CHECKS,
2187
+ DOCTOR_CHECKS_TOKEN,
2188
+ DiscoveryCommands,
2189
+ DiscoveryScanCommand,
2190
+ DiscoverySnapshotDoctorCheck,
2191
+ DoctorCommands,
2192
+ DoctorFlow,
2193
+ MANIFEST_ACCESS_PORT_TOKEN,
2194
+ MANIFEST_CHECKS_TOKEN,
2195
+ ManifestCheckCommand,
2196
+ ManifestCliFlow,
2197
+ ManifestCommands,
2198
+ ManifestDumpCommand,
2199
+ ManifestHashCommand,
2200
+ ManifestValidateCommand,
2201
+ MfaSetupFlow,
2202
+ PLATFORM_DOCTOR_CHECK_PROVIDERS,
2203
+ PlanCatalogDoctorCheck,
2204
+ USER_MANAGEMENT_PORT_TOKEN,
2205
+ USER_PORT_TOKEN,
2206
+ UserCommands,
2207
+ UserPortDoctorCheck,
2208
+ WhoAmIFlow,
2209
+ applyFragmentBlocks,
2210
+ extractModelBlocks,
2211
+ extractModelNames
2212
+ };