@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.
@@ -0,0 +1,548 @@
1
+ import { MfaService, AdminAuditService, AdminManifestService, DiscoverySnapshot, ProviderSpec, DiscoveryScanner } from '@saasicat/nest';
2
+ import { UserPort, PlatformUserDto, AuditQueryPort, AuditEntry, AdminManifest, ManifestAccessPort, PlanCatalog, UserManagementPort } from '@saasicat/types';
3
+ import { Type, DynamicModule } from '@nestjs/common';
4
+ import { CommandRunner } from 'nest-commander';
5
+
6
+ declare const CLI_CONTEXT_CONFIG_TOKEN: unique symbol;
7
+ declare const USER_PORT_TOKEN: unique symbol;
8
+ /** Write/list operations for the shared `<app> user` command. */
9
+ declare const USER_MANAGEMENT_PORT_TOKEN: unique symbol;
10
+ declare const AUDIT_QUERY_PORT_TOKEN: unique symbol;
11
+ /** List of DoctorCheck implementations — consumers may extend. */
12
+ declare const DOCTOR_CHECKS_TOKEN: unique symbol;
13
+ declare const MANIFEST_ACCESS_PORT_TOKEN: unique symbol;
14
+ /** List of ManifestCheck implementations — consumers may extend. */
15
+ declare const MANIFEST_CHECKS_TOKEN: unique symbol;
16
+
17
+ interface CliContextConfig {
18
+ /**
19
+ * Env-var name for the admin email (e.g. `MYAPP_ADMIN_EMAIL`).
20
+ * Platform default: `SAAS_ADMIN_EMAIL`.
21
+ */
22
+ adminEmailEnvVar: string;
23
+ /**
24
+ * Function that returns `true` when the CLI runs against a production
25
+ * environment. The consumer checks its own env vars (e.g.
26
+ * `MYAPP_ENV === 'production'`, `DATABASE_URL` host, etc.).
27
+ */
28
+ isProductionEnvironment: () => boolean;
29
+ /**
30
+ * Env-var name for the MFA-bypass switch (e.g. `MYAPP_SKIP_MFA`).
31
+ * Platform default: `SAAS_PLATFORM_SKIP_MFA`. The bypass only takes
32
+ * effect when `isProductionEnvironment()` is `false`.
33
+ */
34
+ mfaSkipEnvVar: string;
35
+ /**
36
+ * Display issuer for `<app> admin mfa-setup` in the authenticator
37
+ * (e.g. "DemoApp SuperAdmin", "ClubApp SuperAdmin").
38
+ * Default: `"SuperAdmin"`.
39
+ */
40
+ mfaIssuer?: string;
41
+ }
42
+ interface CliIdentity {
43
+ email: string;
44
+ host: string;
45
+ /** "cli:<email>:<host>" — canonical audit actor tag. */
46
+ actor: string;
47
+ }
48
+ declare class CliContextService {
49
+ private readonly config;
50
+ private readonly users;
51
+ private readonly mfa;
52
+ private readonly audit;
53
+ constructor(config: CliContextConfig, users: UserPort, mfa: MfaService, audit: AdminAuditService);
54
+ resolveIdentity(asFlag?: string): CliIdentity;
55
+ /**
56
+ * Loads + validates the user for a CLI identity:
57
+ * - user exists + active
58
+ * - user has platform role SUPER_ADMIN
59
+ *
60
+ * Throws `CliError(NOT_SUPER_ADMIN, exit=2)` otherwise.
61
+ */
62
+ ensureSuperAdmin(identity: CliIdentity): Promise<PlatformUserDto>;
63
+ /**
64
+ * Prompts the user for a TOTP code and verifies it against the stored
65
+ * secret (via the platform `MfaService` → `MfaPort`).
66
+ *
67
+ * Bypass: `process.env[mfaSkipEnvVar] === '1'` AND `!isProductionEnvironment()`.
68
+ */
69
+ requireMfa(userId: string): Promise<void>;
70
+ ensureProductionConfirmation(opts?: {
71
+ yes?: boolean;
72
+ }): Promise<void>;
73
+ /**
74
+ * Writes an audit-log entry with the CLI actor tag. Wrapper over
75
+ * `AdminAuditService.log` with automatic `fromCli` construction.
76
+ */
77
+ log(input: {
78
+ identity: CliIdentity;
79
+ userId: string;
80
+ entity: string;
81
+ entityId: string;
82
+ action: string;
83
+ changes?: Record<string, unknown>;
84
+ }): Promise<void>;
85
+ table(rows: Record<string, unknown>[]): void;
86
+ /**
87
+ * Reads a line from stdin. Override hook for tests: set
88
+ * `process.env.SAAS_PLATFORM_CLI_PROMPT_REPLY` to a reply, then
89
+ * the method succeeds without interaction.
90
+ */
91
+ prompt(question: string): Promise<string>;
92
+ }
93
+ /**
94
+ * Structured CLI error with `exitCode` mapping per
95
+ * `cli-conventions.md` §6:
96
+ *
97
+ * 1 = user error, 2 = auth, 3 = MFA, 4 = connectivity,
98
+ * 5 = permission, 6 = conflict, 7 = drift, 99 = internal.
99
+ */
100
+ declare class CliError extends Error {
101
+ readonly code: string;
102
+ readonly exitCode: number;
103
+ constructor(code: string, message: string, exitCode: number);
104
+ }
105
+
106
+ interface MfaSetupOptions {
107
+ /** `--as <email>` override for the actor identity. */
108
+ asFlag?: string;
109
+ /**
110
+ * Issuer string shown in the authenticator (e.g. "DemoApp SuperAdmin",
111
+ * "ClubApp SuperAdmin"). Consumers set their own app name.
112
+ */
113
+ issuer: string;
114
+ /**
115
+ * Optional: confirms overwriting an existing secret. Default: the first
116
+ * re-setup request must be confirmed interactively with `yes`, otherwise
117
+ * it is aborted.
118
+ */
119
+ force?: boolean;
120
+ }
121
+ interface MfaSetupResult {
122
+ /** Base32-encoded TOTP secret. */
123
+ secret: string;
124
+ /** otpauth URI for a QR-code generator (authenticator app). */
125
+ otpauthUri: string;
126
+ /** Email + ID of the user whose secret was just created. */
127
+ userId: string;
128
+ userEmail: string;
129
+ }
130
+ declare class MfaSetupFlow {
131
+ private readonly ctx;
132
+ private readonly mfa;
133
+ constructor(ctx: CliContextService, mfa: MfaService);
134
+ /**
135
+ * Runs the full setup flow. Throws `CliError` subclasses on
136
+ * auth/identity/confirmation errors.
137
+ */
138
+ run(options: MfaSetupOptions): Promise<MfaSetupResult>;
139
+ /**
140
+ * Helper: returns a human-readable output block with secret + otpauthUri
141
+ * for `console.log` in the consumer command. Consumers may prepend their
142
+ * own QR-code renderer (e.g. `qrcode-terminal`).
143
+ */
144
+ formatSetupResult(result: MfaSetupResult): string;
145
+ }
146
+
147
+ interface WhoAmIResult {
148
+ email: string;
149
+ host: string;
150
+ actor: string;
151
+ userId: string | null;
152
+ isSuperAdmin: boolean;
153
+ mfaEnabled: boolean;
154
+ isProduction: boolean;
155
+ mfaSkipActive: boolean;
156
+ }
157
+ declare class WhoAmIFlow {
158
+ private readonly config;
159
+ private readonly ctx;
160
+ private readonly mfa;
161
+ constructor(config: CliContextConfig, ctx: CliContextService, mfa: MfaService);
162
+ run(asFlag?: string): Promise<WhoAmIResult>;
163
+ formatResult(r: WhoAmIResult): string;
164
+ }
165
+
166
+ interface AuditTailOptions {
167
+ actor?: string;
168
+ action?: string;
169
+ entity?: string;
170
+ since?: string;
171
+ /** Default 50, max 500 — enforced by the consumer adapter. */
172
+ limit?: number;
173
+ }
174
+ declare class AuditTailFlow {
175
+ private readonly auditQuery;
176
+ constructor(auditQuery: AuditQueryPort);
177
+ run(options?: AuditTailOptions): Promise<AuditEntry[]>;
178
+ /** Format the result as an ASCII table for `console.table`. */
179
+ formatRows(entries: AuditEntry[]): Record<string, string>[];
180
+ private truncate;
181
+ }
182
+
183
+ type CheckSeverity = 'ok' | 'warning' | 'error';
184
+ interface DoctorCheck {
185
+ /** Unique slug (e.g. "platform.user-port", "demoapp.kosit-sidecar"). */
186
+ readonly id: string;
187
+ /** Display text in the output. */
188
+ readonly label: string;
189
+ run(): Promise<DoctorCheckResult>;
190
+ }
191
+ interface DoctorCheckResult {
192
+ severity: CheckSeverity;
193
+ message: string;
194
+ /** Optional: detail data for the JSON output. */
195
+ details?: Record<string, unknown>;
196
+ }
197
+ interface DoctorReport {
198
+ /** Overall status = max(severity) across all checks. */
199
+ overall: CheckSeverity;
200
+ checks: Array<{
201
+ id: string;
202
+ label: string;
203
+ severity: CheckSeverity;
204
+ message: string;
205
+ details?: Record<string, unknown>;
206
+ }>;
207
+ }
208
+ declare class DoctorFlow {
209
+ private readonly checks;
210
+ constructor(checks: DoctorCheck[]);
211
+ run(): Promise<DoctorReport>;
212
+ /** Returns the appropriate CLI exit code: 0 for `ok`/`warning`, 4 for `error`. */
213
+ exitCodeFor(report: DoctorReport): number;
214
+ formatReport(report: DoctorReport): string;
215
+ }
216
+
217
+ interface ManifestCheckResult {
218
+ severity: 'ok' | 'warning' | 'error';
219
+ message: string;
220
+ /** Optional: affected paths/keys for detailed output. */
221
+ paths?: string[];
222
+ }
223
+ interface ManifestCheck {
224
+ readonly id: string;
225
+ readonly label: string;
226
+ run(manifest: AdminManifest): ManifestCheckResult;
227
+ }
228
+ declare const DEFAULT_MANIFEST_CHECKS: ManifestCheck[];
229
+
230
+ interface ManifestCheckReport {
231
+ overall: 'ok' | 'warning' | 'error';
232
+ checks: Array<{
233
+ id: string;
234
+ label: string;
235
+ severity: 'ok' | 'warning' | 'error';
236
+ message: string;
237
+ paths?: string[];
238
+ }>;
239
+ }
240
+ declare class ManifestCliFlow {
241
+ private readonly access;
242
+ private readonly checks;
243
+ constructor(access: ManifestAccessPort, checks: ManifestCheck[]);
244
+ /** `<app> manifest dump` — JSON output of the current manifest. */
245
+ dump(): AdminManifest;
246
+ /**
247
+ * `<app> manifest hash` — canonical manifestHash value. Returns
248
+ * the value from `build.manifestHash`. Consumers can pin this in CI
249
+ * (`expected-hash.txt`) and check for drift.
250
+ */
251
+ hash(): string;
252
+ /**
253
+ * `<app> manifest validate` — returns `true` when all structures
254
+ * are present. Deeper schema validation runs separately via Ajv with
255
+ * `@saasicat/spec/schemas/admin-manifest.schema.json`;
256
+ * this helper provides the quick diagnostic without the Ajv cost.
257
+ */
258
+ validate(): {
259
+ ok: boolean;
260
+ reason?: string;
261
+ };
262
+ /**
263
+ * `<app> manifest diff <expected.json>` — flat diff over the two
264
+ * manifest hashes plus list differences for top-level fields. Returns
265
+ * `null` when the manifests are identical.
266
+ */
267
+ diff(expected: AdminManifest): ManifestDiff | null;
268
+ /**
269
+ * `<app> manifest check` — runs all registered manifest checks.
270
+ * Aggregates severity (ok/warning/error) into `overall`. The consumer
271
+ * maps `error` to exit code 7 (drift) per `cli-conventions.md` §6.
272
+ */
273
+ runChecks(): Promise<ManifestCheckReport>;
274
+ /** Returns the appropriate CLI exit code: 0 for `ok`/`warning`, 7 for `error` (drift). */
275
+ exitCodeFor(report: ManifestCheckReport): number;
276
+ formatReport(report: ManifestCheckReport): string;
277
+ }
278
+ interface ManifestDiff {
279
+ currentHash: string | null;
280
+ expectedHash: string | null;
281
+ componentKeysAdded: string[];
282
+ componentKeysRemoved: string[];
283
+ }
284
+
285
+ declare class PlanCatalogDoctorCheck implements DoctorCheck {
286
+ private readonly catalog;
287
+ readonly id = "platform.plan-catalog";
288
+ readonly label = "Plan-Catalog im DI";
289
+ constructor(catalog: PlanCatalog);
290
+ run(): Promise<DoctorCheckResult>;
291
+ }
292
+ declare class DiscoverySnapshotDoctorCheck implements DoctorCheck {
293
+ private readonly snapshot;
294
+ readonly id = "platform.discovery-snapshot";
295
+ readonly label = "Discovery-Snapshot beim Boot";
296
+ constructor(snapshot: DiscoverySnapshot);
297
+ run(): Promise<DoctorCheckResult>;
298
+ }
299
+ declare class UserPortDoctorCheck implements DoctorCheck {
300
+ private readonly users;
301
+ readonly id = "platform.user-port";
302
+ readonly label = "UserPort.findByEmail erreichbar";
303
+ constructor(users: UserPort);
304
+ run(): Promise<DoctorCheckResult>;
305
+ }
306
+ declare class AdminManifestDoctorCheck implements DoctorCheck {
307
+ private readonly manifest;
308
+ readonly id = "platform.admin-manifest";
309
+ readonly label = "AdminManifestService liefert Manifest";
310
+ constructor(manifest: AdminManifestService);
311
+ run(): Promise<DoctorCheckResult>;
312
+ }
313
+ /**
314
+ * Default list that consumers can spread in `CliContextModule.forRoot({ doctorChecks })`:
315
+ *
316
+ * ```ts
317
+ * doctorChecks: [
318
+ * ...DEFAULT_DOCTOR_CHECKS,
319
+ * new MyAppKositReachableCheck(),
320
+ * ],
321
+ * ```
322
+ *
323
+ * Platform checks need DI providers — they are instantiated automatically by
324
+ * `CliContextModule` as `extraProviders` when the app sets
325
+ * `defaultDoctorChecks: true`.
326
+ */
327
+ declare const PLATFORM_DOCTOR_CHECK_PROVIDERS: Array<Type<DoctorCheck>>;
328
+
329
+ /** Returns the names of all top-level `model X { ... }` blocks in the schema. */
330
+ declare function extractModelNames(schema: string): string[];
331
+ /**
332
+ * Returns all `model X { ... }` blocks from a fragment as a map
333
+ * `name -> complete block text incl. opening/closing braces`.
334
+ *
335
+ * Delimiting logic: we search for `^model X {` (start of line, possibly with
336
+ * leading whitespace) and close as soon as the brace depth drops back to
337
+ * 0. Strings/comments inside the block are, in simplified terms, not
338
+ * counted, which is robust for Prisma schemas (no curly braces
339
+ * in strings, comments only `//`-style).
340
+ */
341
+ declare function extractModelBlocks(fragment: string): Map<string, string>;
342
+ interface ApplyResult {
343
+ /** Number of models that were added. */
344
+ added: string[];
345
+ /** Number of models that were already present (no write). */
346
+ skipped: string[];
347
+ /** Resulting schema text. When `added.length === 0` identical to the input. */
348
+ schema: string;
349
+ }
350
+ /**
351
+ * Appends missing models from `fragmentBlocks` to the end of `schema`. Existing
352
+ * models (same name) stay unchanged and are listed in `skipped`.
353
+ */
354
+ declare function applyFragmentBlocks(schema: string, fragmentBlocks: Map<string, string>, options?: {
355
+ fragmentLabel?: string;
356
+ }): ApplyResult;
357
+
358
+ interface CliContextModuleOptions {
359
+ config: CliContextConfig;
360
+ userPort: ProviderSpec<UserPort>;
361
+ /**
362
+ * Optional: audit query port for `AuditTailFlow`. If not set,
363
+ * `AuditTailFlow` rejects with a DI error — `<app> audit tail` is then
364
+ * not available.
365
+ */
366
+ auditQueryPort?: ProviderSpec<AuditQueryPort>;
367
+ /**
368
+ * Optional: list of DoctorChecks for `DoctorFlow`. Default: empty
369
+ * — `<app> doctor` runs but returns no content. Consumers register
370
+ * project-specific checks.
371
+ *
372
+ * Note: if `defaultDoctorChecks: true`, the 4 platform standard checks
373
+ * (PlanCatalog/Discovery/UserPort/AdminManifest) are registered **in
374
+ * addition** to this list.
375
+ */
376
+ doctorChecks?: ProviderSpec<DoctorCheck[]>;
377
+ /**
378
+ * Default `false`. If `true`, the platform registers the four standard
379
+ * checks from `PLATFORM_DOCTOR_CHECK_PROVIDERS` in addition to
380
+ * `doctorChecks`. Recommended for all apps that take `<app> doctor` seriously.
381
+ */
382
+ defaultDoctorChecks?: boolean;
383
+ /**
384
+ * Optional: ManifestAccessPort for `<app> manifest dump|hash|check|...`.
385
+ * If not set, `ManifestCliFlow` is not registered.
386
+ */
387
+ manifestAccessPort?: ProviderSpec<ManifestAccessPort>;
388
+ /**
389
+ * Optional: full ManifestChecks list. Default is the 10
390
+ * `DEFAULT_MANIFEST_CHECKS`. Consumer extensions should pass through
391
+ * `[...DEFAULT_MANIFEST_CHECKS, ...projectSpecific]`.
392
+ */
393
+ manifestChecks?: ProviderSpec<ManifestCheck[]>;
394
+ /**
395
+ * Optional: UserManagementPort for the shared `<app> user` command
396
+ * (create-super-admin/reassign-admin/list/reset-password/deactivate).
397
+ * Without this port `UserCommands` cannot be resolved — register the
398
+ * command only if this port is set.
399
+ */
400
+ userManagementPort?: ProviderSpec<UserManagementPort>;
401
+ /** Register the module globally — default `false`. */
402
+ global?: boolean;
403
+ }
404
+ declare class CliContextModule {
405
+ static forRoot(options: CliContextModuleOptions): DynamicModule;
406
+ }
407
+
408
+ interface AsFlag$2 {
409
+ as?: string;
410
+ }
411
+ declare class ManifestDumpCommand extends CommandRunner {
412
+ private readonly ctx;
413
+ private readonly flow;
414
+ constructor(ctx: CliContextService, flow: ManifestCliFlow);
415
+ run(_args: string[], flags: AsFlag$2): Promise<void>;
416
+ parseAs(v: string): string;
417
+ }
418
+ declare class ManifestHashCommand extends CommandRunner {
419
+ private readonly ctx;
420
+ private readonly flow;
421
+ constructor(ctx: CliContextService, flow: ManifestCliFlow);
422
+ run(_args: string[], flags: AsFlag$2): Promise<void>;
423
+ parseAs(v: string): string;
424
+ }
425
+ declare class ManifestValidateCommand extends CommandRunner {
426
+ private readonly ctx;
427
+ private readonly flow;
428
+ constructor(ctx: CliContextService, flow: ManifestCliFlow);
429
+ run(_args: string[], flags: AsFlag$2): Promise<void>;
430
+ parseAs(v: string): string;
431
+ }
432
+ declare class ManifestCheckCommand extends CommandRunner {
433
+ private readonly ctx;
434
+ private readonly flow;
435
+ constructor(ctx: CliContextService, flow: ManifestCliFlow);
436
+ run(_args: string[], flags: AsFlag$2): Promise<void>;
437
+ parseAs(v: string): string;
438
+ }
439
+ declare class ManifestCommands extends CommandRunner {
440
+ run(): Promise<void>;
441
+ }
442
+
443
+ interface AsFlag$1 {
444
+ as?: string;
445
+ }
446
+ interface MfaSetupFlags extends AsFlag$1 {
447
+ force?: boolean;
448
+ }
449
+ declare class AdminWhoamiCommand extends CommandRunner {
450
+ private readonly flow;
451
+ constructor(flow: WhoAmIFlow);
452
+ run(_args: string[], flags: AsFlag$1): Promise<void>;
453
+ parseAs(v: string): string;
454
+ }
455
+ declare class AdminMfaSetupCommand extends CommandRunner {
456
+ private readonly config;
457
+ private readonly flow;
458
+ constructor(config: CliContextConfig, flow: MfaSetupFlow);
459
+ run(_args: string[], flags: MfaSetupFlags): Promise<void>;
460
+ parseAs(v: string): string;
461
+ parseForce(): boolean;
462
+ }
463
+ declare class AdminCommands extends CommandRunner {
464
+ run(): Promise<void>;
465
+ }
466
+
467
+ interface TailFlags {
468
+ as?: string;
469
+ actor?: string;
470
+ action?: string;
471
+ entity?: string;
472
+ since?: string;
473
+ limit?: number;
474
+ }
475
+ declare class AuditTailCommand extends CommandRunner {
476
+ private readonly ctx;
477
+ private readonly flow;
478
+ constructor(ctx: CliContextService, flow: AuditTailFlow);
479
+ run(_args: string[], flags: TailFlags): Promise<void>;
480
+ parseAs(v: string): string;
481
+ parseActor(v: string): string;
482
+ parseAction(v: string): string;
483
+ parseEntity(v: string): string;
484
+ parseSince(v: string): string;
485
+ parseLimit(v: string): number;
486
+ }
487
+ declare class AuditCommands extends CommandRunner {
488
+ run(): Promise<void>;
489
+ }
490
+
491
+ interface AsFlag {
492
+ as?: string;
493
+ }
494
+ declare class DoctorCommands extends CommandRunner {
495
+ private readonly ctx;
496
+ private readonly flow;
497
+ constructor(ctx: CliContextService, flow: DoctorFlow);
498
+ run(_args: string[], flags: AsFlag): Promise<void>;
499
+ parseAs(v: string): string;
500
+ }
501
+
502
+ interface ScanFlags {
503
+ out?: string;
504
+ nonFatal?: boolean;
505
+ }
506
+ declare class DiscoveryScanCommand extends CommandRunner {
507
+ private readonly scanner;
508
+ private readonly configuredPath;
509
+ constructor(scanner?: DiscoveryScanner | null, configuredPath?: string | null);
510
+ run(_args: string[], flags: ScanFlags): Promise<void>;
511
+ /** Exit 4 (analogous to Seed-Gate/Preflight) — only a warning with `--non-fatal`. */
512
+ private fail;
513
+ parseOut(v: string): string;
514
+ parseNonFatal(): boolean;
515
+ }
516
+ declare class DiscoveryCommands extends CommandRunner {
517
+ run(): Promise<void>;
518
+ }
519
+
520
+ interface UserFlags {
521
+ as?: string;
522
+ to?: string;
523
+ reason?: string;
524
+ yes?: boolean;
525
+ first?: string;
526
+ last?: string;
527
+ password?: string;
528
+ }
529
+ declare class UserCommands extends CommandRunner {
530
+ private readonly ctx;
531
+ private readonly users;
532
+ constructor(ctx: CliContextService, users: UserManagementPort);
533
+ run(args: string[], flags: UserFlags): Promise<void>;
534
+ private createSuperAdmin;
535
+ private reassignAdmin;
536
+ private list;
537
+ private resetPassword;
538
+ private deactivate;
539
+ parseAs(val: string): string;
540
+ parseTo(val: string): string;
541
+ parseReason(val: string): string;
542
+ parseYes(): boolean;
543
+ parseFirst(val: string): string;
544
+ parseLast(val: string): string;
545
+ parsePassword(val: string): string;
546
+ }
547
+
548
+ export { AUDIT_QUERY_PORT_TOKEN, AdminCommands, AdminManifestDoctorCheck, AdminMfaSetupCommand, AdminWhoamiCommand, type ApplyResult, AuditCommands, AuditTailCommand, AuditTailFlow, type AuditTailOptions, CLI_CONTEXT_CONFIG_TOKEN, type CheckSeverity, type CliContextConfig, CliContextModule, type CliContextModuleOptions, CliContextService, CliError, type CliIdentity, DEFAULT_MANIFEST_CHECKS, DOCTOR_CHECKS_TOKEN, DiscoveryCommands, DiscoveryScanCommand, DiscoverySnapshotDoctorCheck, type DoctorCheck, type DoctorCheckResult, DoctorCommands, DoctorFlow, type DoctorReport, MANIFEST_ACCESS_PORT_TOKEN, MANIFEST_CHECKS_TOKEN, type ManifestCheck, ManifestCheckCommand, type ManifestCheckReport, type ManifestCheckResult, ManifestCliFlow, ManifestCommands, type ManifestDiff, ManifestDumpCommand, ManifestHashCommand, ManifestValidateCommand, MfaSetupFlow, type MfaSetupOptions, type MfaSetupResult, PLATFORM_DOCTOR_CHECK_PROVIDERS, PlanCatalogDoctorCheck, USER_MANAGEMENT_PORT_TOKEN, USER_PORT_TOKEN, UserCommands, UserPortDoctorCheck, WhoAmIFlow, type WhoAmIResult, applyFragmentBlocks, extractModelBlocks, extractModelNames };