@saasicat/cli 0.18.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +119 -119
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +119 -119
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -136,7 +136,7 @@ var CliContextService = class {
|
|
|
136
136
|
const fromEnv = process.env[this.config.adminEmailEnvVar] ?? "";
|
|
137
137
|
const email = (asFlag ?? fromEnv).trim().toLowerCase();
|
|
138
138
|
if (!email) {
|
|
139
|
-
throw new CliError("NO_IDENTITY", `
|
|
139
|
+
throw new CliError("NO_IDENTITY", `No admin identity set. Please set $${this.config.adminEmailEnvVar} or pass --as <email>.`, 2);
|
|
140
140
|
}
|
|
141
141
|
const host = os.hostname();
|
|
142
142
|
return {
|
|
@@ -155,10 +155,10 @@ var CliContextService = class {
|
|
|
155
155
|
async ensureSuperAdmin(identity) {
|
|
156
156
|
const user = await this.users.findByEmail(identity.email);
|
|
157
157
|
if (!user || user.deletedAt || !user.isActive) {
|
|
158
|
-
throw new CliError("USER_NOT_FOUND", `SUPER_ADMIN-User ${identity.email}
|
|
158
|
+
throw new CliError("USER_NOT_FOUND", `SUPER_ADMIN-User ${identity.email} not found or inactive.`, 2);
|
|
159
159
|
}
|
|
160
160
|
if (user.platformRole !== "SUPER_ADMIN") {
|
|
161
|
-
throw new CliError("NOT_SUPER_ADMIN", `User ${identity.email}
|
|
161
|
+
throw new CliError("NOT_SUPER_ADMIN", `User ${identity.email} has role ${user.platformRole} \u2014 only SUPER_ADMIN may use this CLI.`, 2);
|
|
162
162
|
}
|
|
163
163
|
return user;
|
|
164
164
|
}
|
|
@@ -177,7 +177,7 @@ var CliContextService = class {
|
|
|
177
177
|
}
|
|
178
178
|
const enabled = await this.mfa.isEnabled(userId);
|
|
179
179
|
if (!enabled) {
|
|
180
|
-
throw new CliError("MFA_NOT_SET_UP", "MFA
|
|
180
|
+
throw new CliError("MFA_NOT_SET_UP", "MFA is not configured. Run 'admin mfa-setup' first.", 3);
|
|
181
181
|
}
|
|
182
182
|
const code = await this.prompt("TOTP-Code: ");
|
|
183
183
|
const ok2 = await this.mfa.verify({
|
|
@@ -185,7 +185,7 @@ var CliContextService = class {
|
|
|
185
185
|
code
|
|
186
186
|
});
|
|
187
187
|
if (!ok2) {
|
|
188
|
-
throw new CliError("MFA_FAILED", "TOTP
|
|
188
|
+
throw new CliError("MFA_FAILED", "Invalid TOTP code.", 3);
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
// ---------------------------------------------------------------------
|
|
@@ -194,9 +194,9 @@ var CliContextService = class {
|
|
|
194
194
|
async ensureProductionConfirmation(opts = {}) {
|
|
195
195
|
if (!this.config.isProductionEnvironment()) return;
|
|
196
196
|
if (opts.yes) return;
|
|
197
|
-
const answer = await this.prompt("
|
|
197
|
+
const answer = await this.prompt("Type production to confirm: ");
|
|
198
198
|
if (answer.trim().toLowerCase() !== "production") {
|
|
199
|
-
throw new CliError("PRODUCTION_CONFIRM_ABORTED", "Production
|
|
199
|
+
throw new CliError("PRODUCTION_CONFIRM_ABORTED", "Production confirmation aborted.", 1);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
// ---------------------------------------------------------------------
|
|
@@ -224,7 +224,7 @@ var CliContextService = class {
|
|
|
224
224
|
// ---------------------------------------------------------------------
|
|
225
225
|
table(rows) {
|
|
226
226
|
if (rows.length === 0) {
|
|
227
|
-
console.log("\u2014
|
|
227
|
+
console.log("\u2014 no entries \u2014");
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
console.table(rows);
|
|
@@ -306,9 +306,9 @@ var MfaSetupFlow = class {
|
|
|
306
306
|
const user = await this.ctx.ensureSuperAdmin(identity);
|
|
307
307
|
const alreadyEnabled = await this.mfa.isEnabled(user.id);
|
|
308
308
|
if (alreadyEnabled && !options.force) {
|
|
309
|
-
const answer = await this.ctx.prompt("MFA
|
|
309
|
+
const answer = await this.ctx.prompt("MFA is already configured. Type `yes` to overwrite the secret: ");
|
|
310
310
|
if (answer.trim().toLowerCase() !== "yes") {
|
|
311
|
-
throw new CliError("MFA_SETUP_ABORTED", "Re-
|
|
311
|
+
throw new CliError("MFA_SETUP_ABORTED", "Re-setup not confirmed \u2014 the existing secret stays active.", 1);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
const setup = await this.mfa.setup(user.id, user.email, options.issuer);
|
|
@@ -336,15 +336,15 @@ var MfaSetupFlow = class {
|
|
|
336
336
|
*/
|
|
337
337
|
formatSetupResult(result) {
|
|
338
338
|
return [
|
|
339
|
-
`MFA
|
|
339
|
+
`MFA setup for ${result.userEmail} completed.`,
|
|
340
340
|
"",
|
|
341
341
|
`Secret (Base32): ${result.secret}`,
|
|
342
342
|
`otpauth-URI: ${result.otpauthUri}`,
|
|
343
343
|
"",
|
|
344
|
-
"
|
|
345
|
-
"1Password, \u2026)
|
|
346
|
-
"
|
|
347
|
-
"
|
|
344
|
+
"Import the otpauth URI into your authenticator (Google Authenticator,",
|
|
345
|
+
"1Password, \u2026), or render it as a QR code in a QR generator",
|
|
346
|
+
". Then verify with the first TOTP code that login",
|
|
347
|
+
"works \u2014 otherwise you will lock yourself out of the CLI."
|
|
348
348
|
].join("\n");
|
|
349
349
|
}
|
|
350
350
|
};
|
|
@@ -416,16 +416,16 @@ var WhoAmIFlow = class {
|
|
|
416
416
|
}
|
|
417
417
|
formatResult(r) {
|
|
418
418
|
const lines = [
|
|
419
|
-
`
|
|
419
|
+
`Identity: ${r.email}`,
|
|
420
420
|
`Host: ${r.host}`,
|
|
421
421
|
`Actor-Tag: ${r.actor}`,
|
|
422
|
-
`User
|
|
423
|
-
`
|
|
424
|
-
`MFA
|
|
422
|
+
`User ID: ${r.userId ?? "\u2014 (user not found)"}`,
|
|
423
|
+
`Platform role: ${r.isSuperAdmin ? "SUPER_ADMIN \u2713" : "\u2014 (not a SUPER_ADMIN!)"}`,
|
|
424
|
+
`MFA configured: ${r.mfaEnabled ? "\u2713" : "\u2717 \u2014 run `admin mfa-setup`"}`,
|
|
425
425
|
`Environment: ${r.isProduction ? "PRODUCTION" : "non-production"}`
|
|
426
426
|
];
|
|
427
427
|
if (r.mfaSkipActive) {
|
|
428
|
-
lines.push("\u26A0 MFA
|
|
428
|
+
lines.push("\u26A0 MFA bypass active (SKIP env var set, non-prod)");
|
|
429
429
|
}
|
|
430
430
|
return lines.join("\n");
|
|
431
431
|
}
|
|
@@ -561,7 +561,7 @@ var DoctorFlow = class {
|
|
|
561
561
|
}
|
|
562
562
|
formatReport(report) {
|
|
563
563
|
const lines = [
|
|
564
|
-
`Doctor
|
|
564
|
+
`Doctor check (overall status: ${report.overall.toUpperCase()})`,
|
|
565
565
|
""
|
|
566
566
|
];
|
|
567
567
|
for (const c of report.checks) {
|
|
@@ -634,62 +634,62 @@ __name(allCapabilities, "allCapabilities");
|
|
|
634
634
|
var DEFAULT_MANIFEST_CHECKS = [
|
|
635
635
|
{
|
|
636
636
|
id: "manifest.schema-version",
|
|
637
|
-
label: "schemaVersion
|
|
638
|
-
run: /* @__PURE__ */ __name((m) => m.schemaVersion === 1 ? ok("schemaVersion=1") : err(`
|
|
637
|
+
label: "schemaVersion is 1",
|
|
638
|
+
run: /* @__PURE__ */ __name((m) => m.schemaVersion === 1 ? ok("schemaVersion=1") : err(`Unexpected schemaVersion ${m.schemaVersion}`), "run")
|
|
639
639
|
},
|
|
640
640
|
{
|
|
641
641
|
id: "manifest.hash-format",
|
|
642
|
-
label: "manifestHash
|
|
642
|
+
label: "manifestHash follows the sha256-<base64url> pattern",
|
|
643
643
|
run: /* @__PURE__ */ __name((m) => {
|
|
644
644
|
const hash = m.build?.manifestHash;
|
|
645
|
-
if (!hash) return err("manifestHash
|
|
646
|
-
return /^sha256-[A-Za-z0-9_-]+$/.test(hash) ? ok(hash) : err(`manifestHash
|
|
645
|
+
if (!hash) return err("manifestHash is missing");
|
|
646
|
+
return /^sha256-[A-Za-z0-9_-]+$/.test(hash) ? ok(hash) : err(`manifestHash has the wrong format: ${hash}`);
|
|
647
647
|
}, "run")
|
|
648
648
|
},
|
|
649
649
|
{
|
|
650
650
|
id: "manifest.project-page-component-keys",
|
|
651
|
-
label: "ProjectPage.componentKey
|
|
651
|
+
label: "ProjectPage.componentKey format (lowercase-hyphenated OR namespace.dot)",
|
|
652
652
|
run: /* @__PURE__ */ __name((m) => {
|
|
653
653
|
const bad = [];
|
|
654
654
|
for (const p of allProjectPages(m)) {
|
|
655
655
|
if (!COMPONENT_KEY_PATTERN.test(p.componentKey)) bad.push(p.componentKey);
|
|
656
656
|
}
|
|
657
|
-
return bad.length === 0 ? ok(`${allProjectPages(m).length} ProjectPage(s) ok`) : err(`${bad.length} componentKey(s)
|
|
657
|
+
return bad.length === 0 ? ok(`${allProjectPages(m).length} ProjectPage(s) ok`) : err(`${bad.length} componentKey(s) violate the pattern`, bad);
|
|
658
658
|
}, "run")
|
|
659
659
|
},
|
|
660
660
|
{
|
|
661
661
|
id: "manifest.tenant-action-keys",
|
|
662
|
-
label: "TenantAction.actionKey
|
|
662
|
+
label: "TenantAction.actionKey format (domain.action \u2014 SPEC \xA74.2.1)",
|
|
663
663
|
run: /* @__PURE__ */ __name((m) => {
|
|
664
664
|
const bad = [];
|
|
665
665
|
for (const a of allTenantActions(m)) {
|
|
666
666
|
if (!TENANT_ACTION_KEY_PATTERN.test(a.actionKey)) bad.push(a.actionKey);
|
|
667
667
|
}
|
|
668
|
-
return bad.length === 0 ? ok("
|
|
668
|
+
return bad.length === 0 ? ok("every actionKey follows domain.action") : err(`${bad.length} actionKey(s) violate the pattern`, bad);
|
|
669
669
|
}, "run")
|
|
670
670
|
},
|
|
671
671
|
{
|
|
672
672
|
id: "manifest.audit-action-keys",
|
|
673
|
-
label: "AuditAction.key
|
|
673
|
+
label: "AuditAction.key format (SCREAMING_SNAKE_CASE)",
|
|
674
674
|
run: /* @__PURE__ */ __name((m) => {
|
|
675
675
|
const bad = [];
|
|
676
676
|
for (const a of allAuditActions(m)) {
|
|
677
677
|
if (!ACTION_KEY_PATTERN.test(a.key)) bad.push(a.key);
|
|
678
678
|
}
|
|
679
|
-
return bad.length === 0 ? ok("
|
|
679
|
+
return bad.length === 0 ? ok("every AuditAction.key is SCREAMING_SNAKE_CASE") : err(`${bad.length} AuditAction.key(s) violate the pattern`, bad);
|
|
680
680
|
}, "run")
|
|
681
681
|
},
|
|
682
682
|
{
|
|
683
683
|
id: "manifest.capabilities-pattern",
|
|
684
|
-
label: "Capability
|
|
684
|
+
label: "Capability pattern <domain>.<action> (SPEC \xA74.2.1)",
|
|
685
685
|
run: /* @__PURE__ */ __name((m) => {
|
|
686
686
|
const bad = allCapabilities(m).filter((c) => !CAPABILITY_PATTERN.test(c));
|
|
687
|
-
return bad.length === 0 ? ok(`${allCapabilities(m).length} Capabilities ok`) : err(`${bad.length} Capability/-ies
|
|
687
|
+
return bad.length === 0 ? ok(`${allCapabilities(m).length} Capabilities ok`) : err(`${bad.length} Capability/-ies violate the pattern`, bad);
|
|
688
688
|
}, "run")
|
|
689
689
|
},
|
|
690
690
|
{
|
|
691
691
|
id: "manifest.required-capabilities-known",
|
|
692
|
-
label: "requiredCapability
|
|
692
|
+
label: "requiredCapability references resolve against the capabilities map",
|
|
693
693
|
run: /* @__PURE__ */ __name((m) => {
|
|
694
694
|
const known = new Set(allCapabilities(m));
|
|
695
695
|
const bad = [];
|
|
@@ -700,23 +700,23 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
700
700
|
for (const k of allKpiCards(m)) visit(k.requiredCapability, k.id);
|
|
701
701
|
for (const a of allTenantActions(m)) visit(a.requiredCapability, a.id);
|
|
702
702
|
for (const c of allTenantColumns(m)) visit(c.requiredCapability, c.key);
|
|
703
|
-
return bad.length === 0 ? ok("
|
|
703
|
+
return bad.length === 0 ? ok("every requiredCapability ref resolves") : err(`${bad.length} unknown capability ref(s)`, bad);
|
|
704
704
|
}, "run")
|
|
705
705
|
},
|
|
706
706
|
{
|
|
707
707
|
id: "manifest.route-prefix",
|
|
708
|
-
label: "ProjectPage.route
|
|
708
|
+
label: "ProjectPage.route starts with /admin",
|
|
709
709
|
run: /* @__PURE__ */ __name((m) => {
|
|
710
710
|
const bad = [];
|
|
711
711
|
for (const p of allProjectPages(m)) {
|
|
712
712
|
if (!p.route.startsWith(ROUTE_PREFIX)) bad.push(p.route);
|
|
713
713
|
}
|
|
714
|
-
return bad.length === 0 ? ok("
|
|
714
|
+
return bad.length === 0 ? ok("every ProjectPage route is under /admin") : err(`${bad.length} route(s) without the /admin prefix`, bad);
|
|
715
715
|
}, "run")
|
|
716
716
|
},
|
|
717
717
|
{
|
|
718
718
|
id: "manifest.kpi-slot-priority",
|
|
719
|
-
label: "KpiCard.slotPriority (
|
|
719
|
+
label: "KpiCard.slotPriority (if set) is a finite number",
|
|
720
720
|
run: /* @__PURE__ */ __name((m) => {
|
|
721
721
|
const bad = [];
|
|
722
722
|
for (const k of allKpiCards(m)) {
|
|
@@ -724,12 +724,12 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
724
724
|
bad.push(k.id);
|
|
725
725
|
}
|
|
726
726
|
}
|
|
727
|
-
return bad.length === 0 ? ok("
|
|
727
|
+
return bad.length === 0 ? ok("every slotPriority value is finite") : err(`${bad.length} KpiCard(s) with an invalid slotPriority`, bad);
|
|
728
728
|
}, "run")
|
|
729
729
|
},
|
|
730
730
|
{
|
|
731
731
|
id: "manifest.unique-project-page-ids",
|
|
732
|
-
label: "ProjectPage.id
|
|
732
|
+
label: "ProjectPage.id is unique",
|
|
733
733
|
run: /* @__PURE__ */ __name((m) => {
|
|
734
734
|
const seen = /* @__PURE__ */ new Map();
|
|
735
735
|
for (const p of allProjectPages(m)) {
|
|
@@ -738,12 +738,12 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
738
738
|
const dups = [
|
|
739
739
|
...seen.entries()
|
|
740
740
|
].filter(([, n]) => n > 1).map(([k]) => k);
|
|
741
|
-
return dups.length === 0 ? ok("
|
|
741
|
+
return dups.length === 0 ? ok("every ProjectPage.id is unique") : err(`${dups.length} duplicate ProjectPage.id(s)`, dups);
|
|
742
742
|
}, "run")
|
|
743
743
|
},
|
|
744
744
|
{
|
|
745
745
|
id: "manifest.unique-action-keys",
|
|
746
|
-
label: "actionKeys
|
|
746
|
+
label: "actionKeys are unique per namespace (TenantAction / AuditAction)",
|
|
747
747
|
run: /* @__PURE__ */ __name((m) => {
|
|
748
748
|
const dups = [];
|
|
749
749
|
const tenantSeen = /* @__PURE__ */ new Map();
|
|
@@ -760,21 +760,21 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
760
760
|
for (const [k, n] of auditSeen) {
|
|
761
761
|
if (n > 1) dups.push(`AuditAction:${k}`);
|
|
762
762
|
}
|
|
763
|
-
return dups.length === 0 ? ok("
|
|
763
|
+
return dups.length === 0 ? ok("every actionKey is unique per namespace") : err(`${dups.length} duplicate actionKey(s)`, dups);
|
|
764
764
|
}, "run")
|
|
765
765
|
},
|
|
766
766
|
{
|
|
767
767
|
id: "manifest.tenant-columns-batchable",
|
|
768
|
-
label: "
|
|
768
|
+
label: "tenant columns carry an endpoint path for batch fetching",
|
|
769
769
|
run: /* @__PURE__ */ __name((m) => {
|
|
770
770
|
const bad = [];
|
|
771
771
|
for (const c of allTenantColumns(m)) {
|
|
772
772
|
if (!c.endpoint || c.endpoint.trim().length === 0) bad.push(c.key);
|
|
773
773
|
else if (c.endpoint.includes("{slug}") || c.endpoint.includes("{tenantId}")) {
|
|
774
|
-
bad.push(`${c.key} (per-
|
|
774
|
+
bad.push(`${c.key} (per-tenant instead of batch)`);
|
|
775
775
|
}
|
|
776
776
|
}
|
|
777
|
-
return bad.length === 0 ? ok("
|
|
777
|
+
return bad.length === 0 ? ok("every tenant column supports batch fetching") : err(`${bad.length} TenantColumn(s) violate the batch requirement`, bad);
|
|
778
778
|
}, "run")
|
|
779
779
|
}
|
|
780
780
|
];
|
|
@@ -820,7 +820,7 @@ var ManifestCliFlow = class {
|
|
|
820
820
|
hash() {
|
|
821
821
|
const m = this.access.getManifest();
|
|
822
822
|
const h = m.build?.manifestHash;
|
|
823
|
-
if (!h) throw new Error("manifestHash
|
|
823
|
+
if (!h) throw new Error("manifestHash is missing from the manifest \u2014 a boot-time bug?");
|
|
824
824
|
return h;
|
|
825
825
|
}
|
|
826
826
|
/**
|
|
@@ -834,19 +834,19 @@ var ManifestCliFlow = class {
|
|
|
834
834
|
if (m.schemaVersion !== 1) {
|
|
835
835
|
return {
|
|
836
836
|
ok: false,
|
|
837
|
-
reason: `
|
|
837
|
+
reason: `Unexpected schemaVersion ${m.schemaVersion}`
|
|
838
838
|
};
|
|
839
839
|
}
|
|
840
840
|
if (!m.project?.key) {
|
|
841
841
|
return {
|
|
842
842
|
ok: false,
|
|
843
|
-
reason: "
|
|
843
|
+
reason: "No `project.key` in the manifest"
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
846
|
if (!m.build?.manifestHash) {
|
|
847
847
|
return {
|
|
848
848
|
ok: false,
|
|
849
|
-
reason: "manifestHash
|
|
849
|
+
reason: "manifestHash is missing"
|
|
850
850
|
};
|
|
851
851
|
}
|
|
852
852
|
return {
|
|
@@ -898,7 +898,7 @@ var ManifestCliFlow = class {
|
|
|
898
898
|
id: check.id,
|
|
899
899
|
label: check.label,
|
|
900
900
|
severity: "error",
|
|
901
|
-
message: `
|
|
901
|
+
message: `The check threw an exception: ${message}`
|
|
902
902
|
});
|
|
903
903
|
overall = "error";
|
|
904
904
|
}
|
|
@@ -914,7 +914,7 @@ var ManifestCliFlow = class {
|
|
|
914
914
|
}
|
|
915
915
|
formatReport(report) {
|
|
916
916
|
const lines = [
|
|
917
|
-
`Manifest
|
|
917
|
+
`Manifest check (overall status: ${report.overall.toUpperCase()})`,
|
|
918
918
|
""
|
|
919
919
|
];
|
|
920
920
|
for (const c of report.checks) {
|
|
@@ -976,7 +976,7 @@ var PlanCatalogDoctorCheck = class {
|
|
|
976
976
|
}
|
|
977
977
|
catalog;
|
|
978
978
|
id = "platform.plan-catalog";
|
|
979
|
-
label = "Plan
|
|
979
|
+
label = "Plan catalog in DI";
|
|
980
980
|
constructor(catalog) {
|
|
981
981
|
this.catalog = catalog;
|
|
982
982
|
}
|
|
@@ -985,12 +985,12 @@ var PlanCatalogDoctorCheck = class {
|
|
|
985
985
|
if (plans.length === 0) {
|
|
986
986
|
return {
|
|
987
987
|
severity: "error",
|
|
988
|
-
message: "
|
|
988
|
+
message: "The plan catalog contains no plans \u2014 the onboarding pricing page will be empty."
|
|
989
989
|
};
|
|
990
990
|
}
|
|
991
991
|
return {
|
|
992
992
|
severity: "ok",
|
|
993
|
-
message: `${plans.length}
|
|
993
|
+
message: `${plans.length} plan(s), ${this.catalog.features?.length ?? 0} feature(s) loaded.`,
|
|
994
994
|
details: {
|
|
995
995
|
projectKey: this.catalog.projectKey,
|
|
996
996
|
planIds: plans.map((p) => p.id)
|
|
@@ -1012,7 +1012,7 @@ var DiscoverySnapshotDoctorCheck = class {
|
|
|
1012
1012
|
}
|
|
1013
1013
|
snapshot;
|
|
1014
1014
|
id = "platform.discovery-snapshot";
|
|
1015
|
-
label = "Discovery
|
|
1015
|
+
label = "Discovery snapshot on boot";
|
|
1016
1016
|
constructor(snapshot) {
|
|
1017
1017
|
this.snapshot = snapshot;
|
|
1018
1018
|
}
|
|
@@ -1021,7 +1021,7 @@ var DiscoverySnapshotDoctorCheck = class {
|
|
|
1021
1021
|
if (caps.length === 0) {
|
|
1022
1022
|
return {
|
|
1023
1023
|
severity: "warning",
|
|
1024
|
-
message: "
|
|
1024
|
+
message: "No capabilities discovered \u2014 decorator-carrying modules may be missing from AppModule.imports[]."
|
|
1025
1025
|
};
|
|
1026
1026
|
}
|
|
1027
1027
|
return {
|
|
@@ -1044,7 +1044,7 @@ var UserPortDoctorCheck = class {
|
|
|
1044
1044
|
}
|
|
1045
1045
|
users;
|
|
1046
1046
|
id = "platform.user-port";
|
|
1047
|
-
label = "UserPort.findByEmail
|
|
1047
|
+
label = "UserPort.findByEmail reachable";
|
|
1048
1048
|
constructor(users) {
|
|
1049
1049
|
this.users = users;
|
|
1050
1050
|
}
|
|
@@ -1053,12 +1053,12 @@ var UserPortDoctorCheck = class {
|
|
|
1053
1053
|
await this.users.findByEmail("__doctor-check__@invalid.local");
|
|
1054
1054
|
return {
|
|
1055
1055
|
severity: "ok",
|
|
1056
|
-
message: "UserPort
|
|
1056
|
+
message: "UserPort responds."
|
|
1057
1057
|
};
|
|
1058
1058
|
} catch (err2) {
|
|
1059
1059
|
return {
|
|
1060
1060
|
severity: "error",
|
|
1061
|
-
message: `UserPort
|
|
1061
|
+
message: `UserPort throws: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
1062
1062
|
};
|
|
1063
1063
|
}
|
|
1064
1064
|
}
|
|
@@ -1077,7 +1077,7 @@ var AdminManifestDoctorCheck = class {
|
|
|
1077
1077
|
}
|
|
1078
1078
|
manifest;
|
|
1079
1079
|
id = "platform.admin-manifest";
|
|
1080
|
-
label = "AdminManifestService
|
|
1080
|
+
label = "AdminManifestService returns a manifest";
|
|
1081
1081
|
constructor(manifest) {
|
|
1082
1082
|
this.manifest = manifest;
|
|
1083
1083
|
}
|
|
@@ -1087,12 +1087,12 @@ var AdminManifestDoctorCheck = class {
|
|
|
1087
1087
|
const pageCount = Object.keys(m.navigation?.standardPages ?? {}).length;
|
|
1088
1088
|
return {
|
|
1089
1089
|
severity: "ok",
|
|
1090
|
-
message: `Manifest
|
|
1090
|
+
message: `Manifest with ${pageCount} standard pages, hash ${m.build?.manifestHash?.slice(0, 12) ?? "???"}\u2026`
|
|
1091
1091
|
};
|
|
1092
1092
|
} catch (err2) {
|
|
1093
1093
|
return {
|
|
1094
1094
|
severity: "error",
|
|
1095
|
-
message: `Manifest
|
|
1095
|
+
message: `Manifest build throws: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
1096
1096
|
};
|
|
1097
1097
|
}
|
|
1098
1098
|
}
|
|
@@ -1235,11 +1235,11 @@ function applyFragmentBlocks(schema, fragmentBlocks, options = {}) {
|
|
|
1235
1235
|
const header = options.fragmentLabel ? `
|
|
1236
1236
|
|
|
1237
1237
|
// ============================================================
|
|
1238
|
-
//
|
|
1238
|
+
// Inserted by \`saasicat schema apply\` from ${options.fragmentLabel}
|
|
1239
1239
|
// ============================================================
|
|
1240
1240
|
` : `
|
|
1241
1241
|
|
|
1242
|
-
//
|
|
1242
|
+
// Inserted by \`saasicat schema apply\`
|
|
1243
1243
|
`;
|
|
1244
1244
|
const trimmedSchema = schema.endsWith("\n") ? schema : schema + "\n";
|
|
1245
1245
|
return {
|
|
@@ -1553,7 +1553,7 @@ ManifestDumpCommand = _ts_decorate9([
|
|
|
1553
1553
|
(0, import_common9.Injectable)(),
|
|
1554
1554
|
(0, import_nest_commander.SubCommand)({
|
|
1555
1555
|
name: "dump",
|
|
1556
|
-
description: "
|
|
1556
|
+
description: "Print the manifest as JSON"
|
|
1557
1557
|
}),
|
|
1558
1558
|
_ts_metadata8("design:type", Function),
|
|
1559
1559
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1593,7 +1593,7 @@ ManifestHashCommand = _ts_decorate9([
|
|
|
1593
1593
|
(0, import_common9.Injectable)(),
|
|
1594
1594
|
(0, import_nest_commander.SubCommand)({
|
|
1595
1595
|
name: "hash",
|
|
1596
|
-
description: "manifestHash
|
|
1596
|
+
description: "Print the manifestHash (CI pinning)"
|
|
1597
1597
|
}),
|
|
1598
1598
|
_ts_metadata8("design:type", Function),
|
|
1599
1599
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1615,7 +1615,7 @@ var ManifestValidateCommand = class extends import_nest_commander.CommandRunner
|
|
|
1615
1615
|
await this.ctx.ensureSuperAdmin(identity);
|
|
1616
1616
|
const result = this.flow.validate();
|
|
1617
1617
|
if (result.ok) {
|
|
1618
|
-
process.stdout.write("Manifest
|
|
1618
|
+
process.stdout.write("Manifest is valid \u2713\n");
|
|
1619
1619
|
return;
|
|
1620
1620
|
}
|
|
1621
1621
|
process.stderr.write(`Manifest invalid: ${result.reason}
|
|
@@ -1640,7 +1640,7 @@ ManifestValidateCommand = _ts_decorate9([
|
|
|
1640
1640
|
(0, import_common9.Injectable)(),
|
|
1641
1641
|
(0, import_nest_commander.SubCommand)({
|
|
1642
1642
|
name: "validate",
|
|
1643
|
-
description: "
|
|
1643
|
+
description: "Quick sanity check (schemaVersion + project.key + manifestHash)"
|
|
1644
1644
|
}),
|
|
1645
1645
|
_ts_metadata8("design:type", Function),
|
|
1646
1646
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1683,7 +1683,7 @@ ManifestCheckCommand = _ts_decorate9([
|
|
|
1683
1683
|
(0, import_common9.Injectable)(),
|
|
1684
1684
|
(0, import_nest_commander.SubCommand)({
|
|
1685
1685
|
name: "check",
|
|
1686
|
-
description: "
|
|
1686
|
+
description: "All manifest checks (exit code 7 on error/drift)"
|
|
1687
1687
|
}),
|
|
1688
1688
|
_ts_metadata8("design:type", Function),
|
|
1689
1689
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1696,7 +1696,7 @@ var ManifestCommands = class extends import_nest_commander.CommandRunner {
|
|
|
1696
1696
|
__name(this, "ManifestCommands");
|
|
1697
1697
|
}
|
|
1698
1698
|
async run() {
|
|
1699
|
-
process.stderr.write("
|
|
1699
|
+
process.stderr.write("Specify a sub-command: dump, hash, validate, check.\n");
|
|
1700
1700
|
process.exit(2);
|
|
1701
1701
|
}
|
|
1702
1702
|
};
|
|
@@ -1704,7 +1704,7 @@ ManifestCommands = _ts_decorate9([
|
|
|
1704
1704
|
(0, import_common9.Injectable)(),
|
|
1705
1705
|
(0, import_nest_commander.Command)({
|
|
1706
1706
|
name: "manifest",
|
|
1707
|
-
description: "Manifest
|
|
1707
|
+
description: "Manifest operations (dump, hash, validate, check)",
|
|
1708
1708
|
subCommands: [
|
|
1709
1709
|
ManifestDumpCommand,
|
|
1710
1710
|
ManifestHashCommand,
|
|
@@ -1765,7 +1765,7 @@ AdminWhoamiCommand = _ts_decorate10([
|
|
|
1765
1765
|
(0, import_common10.Injectable)(),
|
|
1766
1766
|
(0, import_nest_commander2.SubCommand)({
|
|
1767
1767
|
name: "whoami",
|
|
1768
|
-
description: "
|
|
1768
|
+
description: "Active CLI identity plus MFA and production status"
|
|
1769
1769
|
}),
|
|
1770
1770
|
_ts_metadata9("design:type", Function),
|
|
1771
1771
|
_ts_metadata9("design:paramtypes", [
|
|
@@ -1817,7 +1817,7 @@ _ts_decorate10([
|
|
|
1817
1817
|
_ts_decorate10([
|
|
1818
1818
|
(0, import_nest_commander2.Option)({
|
|
1819
1819
|
flags: "--force",
|
|
1820
|
-
description: "
|
|
1820
|
+
description: "overwrite an existing secret without asking"
|
|
1821
1821
|
}),
|
|
1822
1822
|
_ts_metadata9("design:type", Function),
|
|
1823
1823
|
_ts_metadata9("design:paramtypes", []),
|
|
@@ -1827,7 +1827,7 @@ AdminMfaSetupCommand = _ts_decorate10([
|
|
|
1827
1827
|
(0, import_common10.Injectable)(),
|
|
1828
1828
|
(0, import_nest_commander2.SubCommand)({
|
|
1829
1829
|
name: "mfa-setup",
|
|
1830
|
-
description: "TOTP
|
|
1830
|
+
description: "Set up TOTP MFA for your own super-admin account"
|
|
1831
1831
|
}),
|
|
1832
1832
|
_ts_param7(0, (0, import_common10.Inject)(CLI_CONTEXT_CONFIG_TOKEN)),
|
|
1833
1833
|
_ts_metadata9("design:type", Function),
|
|
@@ -1841,7 +1841,7 @@ var AdminCommands = class extends import_nest_commander2.CommandRunner {
|
|
|
1841
1841
|
__name(this, "AdminCommands");
|
|
1842
1842
|
}
|
|
1843
1843
|
async run() {
|
|
1844
|
-
process.stderr.write("
|
|
1844
|
+
process.stderr.write("Specify a sub-command: whoami, mfa-setup.\n");
|
|
1845
1845
|
process.exit(2);
|
|
1846
1846
|
}
|
|
1847
1847
|
};
|
|
@@ -1975,7 +1975,7 @@ AuditTailCommand = _ts_decorate11([
|
|
|
1975
1975
|
(0, import_common11.Injectable)(),
|
|
1976
1976
|
(0, import_nest_commander3.SubCommand)({
|
|
1977
1977
|
name: "tail",
|
|
1978
|
-
description: "
|
|
1978
|
+
description: "Most recent audit-log entries (--actor/--action/--entity/--since/--limit)"
|
|
1979
1979
|
}),
|
|
1980
1980
|
_ts_metadata10("design:type", Function),
|
|
1981
1981
|
_ts_metadata10("design:paramtypes", [
|
|
@@ -1988,7 +1988,7 @@ var AuditCommands = class extends import_nest_commander3.CommandRunner {
|
|
|
1988
1988
|
__name(this, "AuditCommands");
|
|
1989
1989
|
}
|
|
1990
1990
|
async run() {
|
|
1991
|
-
process.stderr.write("
|
|
1991
|
+
process.stderr.write("Specify a sub-command: tail.\n");
|
|
1992
1992
|
process.exit(2);
|
|
1993
1993
|
}
|
|
1994
1994
|
};
|
|
@@ -2052,7 +2052,7 @@ DoctorCommands = _ts_decorate12([
|
|
|
2052
2052
|
(0, import_common12.Injectable)(),
|
|
2053
2053
|
(0, import_nest_commander4.Command)({
|
|
2054
2054
|
name: "doctor",
|
|
2055
|
-
description: "Health
|
|
2055
|
+
description: "Health/drift checks (exit code 4 on error)"
|
|
2056
2056
|
}),
|
|
2057
2057
|
_ts_metadata11("design:type", Function),
|
|
2058
2058
|
_ts_metadata11("design:paramtypes", [
|
|
@@ -2095,7 +2095,7 @@ var DiscoveryScanCommand = class extends import_nest_commander5.CommandRunner {
|
|
|
2095
2095
|
}
|
|
2096
2096
|
async run(_args, flags) {
|
|
2097
2097
|
if (!this.scanner) {
|
|
2098
|
-
this.fail("DiscoveryScanner
|
|
2098
|
+
this.fail("DiscoveryScanner is not registered \u2014 import DiscoveryModule.forRoot() in the CLI module.", flags);
|
|
2099
2099
|
return;
|
|
2100
2100
|
}
|
|
2101
2101
|
try {
|
|
@@ -2111,10 +2111,10 @@ var DiscoveryScanCommand = class extends import_nest_commander5.CommandRunner {
|
|
|
2111
2111
|
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
|
|
2112
2112
|
`);
|
|
2113
2113
|
if (target) {
|
|
2114
|
-
process.stdout.write(`Snapshot
|
|
2114
|
+
process.stdout.write(`Snapshot persisted: ${(0, import_node_path.resolve)(target)}
|
|
2115
2115
|
`);
|
|
2116
2116
|
} else {
|
|
2117
|
-
process.stderr.write("
|
|
2117
|
+
process.stderr.write("WARNING: the snapshot was not persisted \u2014 neither snapshotPath (DiscoveryModule.forRoot) configured nor --out given. The seed gate will find no snapshot this way.\n");
|
|
2118
2118
|
}
|
|
2119
2119
|
} catch (err2) {
|
|
2120
2120
|
this.fail(err2 instanceof Error ? err2.message : String(err2), flags);
|
|
@@ -2127,7 +2127,7 @@ var DiscoveryScanCommand = class extends import_nest_commander5.CommandRunner {
|
|
|
2127
2127
|
`);
|
|
2128
2128
|
return;
|
|
2129
2129
|
}
|
|
2130
|
-
process.stderr.write(`[discovery scan]
|
|
2130
|
+
process.stderr.write(`[discovery scan] ERROR: ${message}
|
|
2131
2131
|
`);
|
|
2132
2132
|
process.exit(4);
|
|
2133
2133
|
}
|
|
@@ -2141,7 +2141,7 @@ var DiscoveryScanCommand = class extends import_nest_commander5.CommandRunner {
|
|
|
2141
2141
|
_ts_decorate13([
|
|
2142
2142
|
(0, import_nest_commander5.Option)({
|
|
2143
2143
|
flags: "--out <path>",
|
|
2144
|
-
description: "
|
|
2144
|
+
description: "Additionally write the snapshot to this path"
|
|
2145
2145
|
}),
|
|
2146
2146
|
_ts_metadata12("design:type", Function),
|
|
2147
2147
|
_ts_metadata12("design:paramtypes", [
|
|
@@ -2152,7 +2152,7 @@ _ts_decorate13([
|
|
|
2152
2152
|
_ts_decorate13([
|
|
2153
2153
|
(0, import_nest_commander5.Option)({
|
|
2154
2154
|
flags: "--non-fatal",
|
|
2155
|
-
description: "
|
|
2155
|
+
description: "Report scan errors as a warning only (exit 0) \u2014 staged rollout"
|
|
2156
2156
|
}),
|
|
2157
2157
|
_ts_metadata12("design:type", Function),
|
|
2158
2158
|
_ts_metadata12("design:paramtypes", []),
|
|
@@ -2162,7 +2162,7 @@ DiscoveryScanCommand = _ts_decorate13([
|
|
|
2162
2162
|
(0, import_common13.Injectable)(),
|
|
2163
2163
|
(0, import_nest_commander5.SubCommand)({
|
|
2164
2164
|
name: "scan",
|
|
2165
|
-
description: "
|
|
2165
|
+
description: "Produce and persist a discovery snapshot headlessly (seed gate, #23)"
|
|
2166
2166
|
}),
|
|
2167
2167
|
_ts_param8(0, (0, import_common13.Optional)()),
|
|
2168
2168
|
_ts_param8(0, (0, import_common13.Inject)(import_nest6.DiscoveryScanner)),
|
|
@@ -2179,7 +2179,7 @@ var DiscoveryCommands = class extends import_nest_commander5.CommandRunner {
|
|
|
2179
2179
|
__name(this, "DiscoveryCommands");
|
|
2180
2180
|
}
|
|
2181
2181
|
async run() {
|
|
2182
|
-
process.stderr.write("
|
|
2182
|
+
process.stderr.write("Specify a sub-command: scan.\n");
|
|
2183
2183
|
process.exit(2);
|
|
2184
2184
|
}
|
|
2185
2185
|
};
|
|
@@ -2245,12 +2245,12 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2245
2245
|
case "deactivate":
|
|
2246
2246
|
return this.deactivate(args[1], flags, identity, me.id);
|
|
2247
2247
|
default:
|
|
2248
|
-
throw new CliError("UNKNOWN_SUBCOMMAND", `
|
|
2248
|
+
throw new CliError("UNKNOWN_SUBCOMMAND", `Unknown sub-command: user ${sub ?? "(empty)"}. Available: create-super-admin <email>, reassign-admin <slug>, list <slug>, reset-password <email>, deactivate <email>.`, 1);
|
|
2249
2249
|
}
|
|
2250
2250
|
}
|
|
2251
2251
|
async createSuperAdmin(email, flags, identity, meId, meEmail) {
|
|
2252
2252
|
if (!email) {
|
|
2253
|
-
throw new CliError("MISSING_ARG", "user create-super-admin <email>
|
|
2253
|
+
throw new CliError("MISSING_ARG", "user create-super-admin <email> expects an email address.", 1);
|
|
2254
2254
|
}
|
|
2255
2255
|
await this.ctx.requireMfa(meId);
|
|
2256
2256
|
await this.ctx.ensureProductionConfirmation({
|
|
@@ -2275,20 +2275,20 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2275
2275
|
createdBy: meEmail
|
|
2276
2276
|
}
|
|
2277
2277
|
});
|
|
2278
|
-
console.log(`\u2714 SUPER_ADMIN ${created.email}
|
|
2278
|
+
console.log(`\u2714 SUPER_ADMIN ${created.email} created (by ${meEmail}).`);
|
|
2279
2279
|
console.log(` User-ID: ${created.id}`);
|
|
2280
2280
|
if (generated) {
|
|
2281
|
-
console.log(`
|
|
2282
|
-
console.log(" \u2192
|
|
2281
|
+
console.log(` Password: ${password}`);
|
|
2282
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2283
2283
|
}
|
|
2284
|
-
console.log(`
|
|
2284
|
+
console.log(` Next step: admin mfa-setup for ${created.email}.`);
|
|
2285
2285
|
}
|
|
2286
2286
|
async reassignAdmin(slug, flags, identity, meId) {
|
|
2287
2287
|
if (!slug) {
|
|
2288
|
-
throw new CliError("MISSING_ARG", "user reassign-admin <tenant-slug>
|
|
2288
|
+
throw new CliError("MISSING_ARG", "user reassign-admin <tenant-slug> expects a slug.", 1);
|
|
2289
2289
|
}
|
|
2290
|
-
if (!flags.to) throw new CliError("MISSING_FLAG", "--to=<email>
|
|
2291
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2290
|
+
if (!flags.to) throw new CliError("MISSING_FLAG", "--to=<email> is required.", 1);
|
|
2291
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2292
2292
|
await this.ctx.requireMfa(meId);
|
|
2293
2293
|
const result = await this.users.reassignTenantAdmin(slug, flags.to.toLowerCase());
|
|
2294
2294
|
await this.ctx.log({
|
|
@@ -2306,18 +2306,18 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2306
2306
|
}
|
|
2307
2307
|
});
|
|
2308
2308
|
if (result.created) {
|
|
2309
|
-
console.log(`\u2714
|
|
2309
|
+
console.log(`\u2714 Emergency admin ${result.user.email} created for ${slug}.`);
|
|
2310
2310
|
if (result.oneTimePassword) {
|
|
2311
|
-
console.log(` Initial
|
|
2312
|
-
console.log(" \u2192
|
|
2311
|
+
console.log(` Initial password: ${result.oneTimePassword}`);
|
|
2312
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2313
2313
|
}
|
|
2314
2314
|
} else {
|
|
2315
|
-
console.log(`\u2714 ${result.user.email}
|
|
2315
|
+
console.log(`\u2714 ${result.user.email} is now TENANT_ADMIN of ${slug}.`);
|
|
2316
2316
|
}
|
|
2317
2317
|
}
|
|
2318
2318
|
async list(slug) {
|
|
2319
2319
|
if (!slug) {
|
|
2320
|
-
throw new CliError("MISSING_ARG", "user list <tenant-slug>
|
|
2320
|
+
throw new CliError("MISSING_ARG", "user list <tenant-slug> expects a slug.", 1);
|
|
2321
2321
|
}
|
|
2322
2322
|
const rows = await this.users.listTenantUsers(slug);
|
|
2323
2323
|
this.ctx.table(rows.map((u) => ({
|
|
@@ -2329,9 +2329,9 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2329
2329
|
}
|
|
2330
2330
|
async resetPassword(email, flags, identity, meId) {
|
|
2331
2331
|
if (!email) {
|
|
2332
|
-
throw new CliError("MISSING_ARG", "user reset-password <email>
|
|
2332
|
+
throw new CliError("MISSING_ARG", "user reset-password <email> expects an email address.", 1);
|
|
2333
2333
|
}
|
|
2334
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2334
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2335
2335
|
const result = await this.users.triggerPasswordReset(email.toLowerCase());
|
|
2336
2336
|
await this.ctx.log({
|
|
2337
2337
|
identity,
|
|
@@ -2344,18 +2344,18 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2344
2344
|
}
|
|
2345
2345
|
});
|
|
2346
2346
|
if (result.oneTimePassword) {
|
|
2347
|
-
console.log(`\u2714
|
|
2348
|
-
console.log(`
|
|
2349
|
-
console.log(" \u2192
|
|
2347
|
+
console.log(`\u2714 One-time password set for ${result.user.email}.`);
|
|
2348
|
+
console.log(` Password: ${result.oneTimePassword}`);
|
|
2349
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2350
2350
|
} else {
|
|
2351
|
-
console.log(`\u2714
|
|
2351
|
+
console.log(`\u2714 Password reset triggered for ${result.user.email}.`);
|
|
2352
2352
|
}
|
|
2353
2353
|
}
|
|
2354
2354
|
async deactivate(email, flags, identity, meId) {
|
|
2355
2355
|
if (!email) {
|
|
2356
|
-
throw new CliError("MISSING_ARG", "user deactivate <email>
|
|
2356
|
+
throw new CliError("MISSING_ARG", "user deactivate <email> expects an email address.", 1);
|
|
2357
2357
|
}
|
|
2358
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2358
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2359
2359
|
await this.ctx.requireMfa(meId);
|
|
2360
2360
|
await this.ctx.ensureProductionConfirmation({
|
|
2361
2361
|
yes: flags.yes
|
|
@@ -2372,7 +2372,7 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2372
2372
|
emergency: true
|
|
2373
2373
|
}
|
|
2374
2374
|
});
|
|
2375
|
-
console.log(`\u2714 ${user.email}
|
|
2375
|
+
console.log(`\u2714 ${user.email} deactivated.`);
|
|
2376
2376
|
}
|
|
2377
2377
|
parseAs(val) {
|
|
2378
2378
|
return val;
|
|
@@ -2399,7 +2399,7 @@ var UserCommands = class extends import_nest_commander6.CommandRunner {
|
|
|
2399
2399
|
_ts_decorate14([
|
|
2400
2400
|
(0, import_nest_commander6.Option)({
|
|
2401
2401
|
flags: "--as <email>",
|
|
2402
|
-
description: "CLI
|
|
2402
|
+
description: "CLI identity (otherwise <APP>_ADMIN_EMAIL)"
|
|
2403
2403
|
}),
|
|
2404
2404
|
_ts_metadata13("design:type", Function),
|
|
2405
2405
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2410,7 +2410,7 @@ _ts_decorate14([
|
|
|
2410
2410
|
_ts_decorate14([
|
|
2411
2411
|
(0, import_nest_commander6.Option)({
|
|
2412
2412
|
flags: "--to <email>",
|
|
2413
|
-
description: "
|
|
2413
|
+
description: "Target user (reassign-admin)"
|
|
2414
2414
|
}),
|
|
2415
2415
|
_ts_metadata13("design:type", Function),
|
|
2416
2416
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2421,7 +2421,7 @@ _ts_decorate14([
|
|
|
2421
2421
|
_ts_decorate14([
|
|
2422
2422
|
(0, import_nest_commander6.Option)({
|
|
2423
2423
|
flags: "--reason <text>",
|
|
2424
|
-
description: "
|
|
2424
|
+
description: "Reason (audit)"
|
|
2425
2425
|
}),
|
|
2426
2426
|
_ts_metadata13("design:type", Function),
|
|
2427
2427
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2432,7 +2432,7 @@ _ts_decorate14([
|
|
|
2432
2432
|
_ts_decorate14([
|
|
2433
2433
|
(0, import_nest_commander6.Option)({
|
|
2434
2434
|
flags: "-y, --yes",
|
|
2435
|
-
description: "
|
|
2435
|
+
description: "Skip the production confirmation"
|
|
2436
2436
|
}),
|
|
2437
2437
|
_ts_metadata13("design:type", Function),
|
|
2438
2438
|
_ts_metadata13("design:paramtypes", []),
|
|
@@ -2441,7 +2441,7 @@ _ts_decorate14([
|
|
|
2441
2441
|
_ts_decorate14([
|
|
2442
2442
|
(0, import_nest_commander6.Option)({
|
|
2443
2443
|
flags: "--first <name>",
|
|
2444
|
-
description: "
|
|
2444
|
+
description: "First name (create-super-admin)"
|
|
2445
2445
|
}),
|
|
2446
2446
|
_ts_metadata13("design:type", Function),
|
|
2447
2447
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2452,7 +2452,7 @@ _ts_decorate14([
|
|
|
2452
2452
|
_ts_decorate14([
|
|
2453
2453
|
(0, import_nest_commander6.Option)({
|
|
2454
2454
|
flags: "--last <name>",
|
|
2455
|
-
description: "
|
|
2455
|
+
description: "Last name (create-super-admin)"
|
|
2456
2456
|
}),
|
|
2457
2457
|
_ts_metadata13("design:type", Function),
|
|
2458
2458
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2463,7 +2463,7 @@ _ts_decorate14([
|
|
|
2463
2463
|
_ts_decorate14([
|
|
2464
2464
|
(0, import_nest_commander6.Option)({
|
|
2465
2465
|
flags: "--password <pwd>",
|
|
2466
|
-
description: "
|
|
2466
|
+
description: "Password (create-super-admin; generated when omitted)"
|
|
2467
2467
|
}),
|
|
2468
2468
|
_ts_metadata13("design:type", Function),
|
|
2469
2469
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2475,7 +2475,7 @@ UserCommands = _ts_decorate14([
|
|
|
2475
2475
|
(0, import_common14.Injectable)(),
|
|
2476
2476
|
(0, import_nest_commander6.Command)({
|
|
2477
2477
|
name: "user",
|
|
2478
|
-
description: "User
|
|
2478
|
+
description: "User operations (create-super-admin, reassign-admin, list, reset-password, deactivate)"
|
|
2479
2479
|
}),
|
|
2480
2480
|
_ts_param9(1, (0, import_common14.Inject)(USER_MANAGEMENT_PORT_TOKEN)),
|
|
2481
2481
|
_ts_metadata13("design:type", Function),
|