@saasicat/cli 0.18.1 → 0.21.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.js
CHANGED
|
@@ -53,7 +53,7 @@ var CliContextService = class {
|
|
|
53
53
|
const fromEnv = process.env[this.config.adminEmailEnvVar] ?? "";
|
|
54
54
|
const email = (asFlag ?? fromEnv).trim().toLowerCase();
|
|
55
55
|
if (!email) {
|
|
56
|
-
throw new CliError("NO_IDENTITY", `
|
|
56
|
+
throw new CliError("NO_IDENTITY", `No admin identity set. Please set $${this.config.adminEmailEnvVar} or pass --as <email>.`, 2);
|
|
57
57
|
}
|
|
58
58
|
const host = os.hostname();
|
|
59
59
|
return {
|
|
@@ -72,10 +72,10 @@ var CliContextService = class {
|
|
|
72
72
|
async ensureSuperAdmin(identity) {
|
|
73
73
|
const user = await this.users.findByEmail(identity.email);
|
|
74
74
|
if (!user || user.deletedAt || !user.isActive) {
|
|
75
|
-
throw new CliError("USER_NOT_FOUND", `SUPER_ADMIN-User ${identity.email}
|
|
75
|
+
throw new CliError("USER_NOT_FOUND", `SUPER_ADMIN-User ${identity.email} not found or inactive.`, 2);
|
|
76
76
|
}
|
|
77
77
|
if (user.platformRole !== "SUPER_ADMIN") {
|
|
78
|
-
throw new CliError("NOT_SUPER_ADMIN", `User ${identity.email}
|
|
78
|
+
throw new CliError("NOT_SUPER_ADMIN", `User ${identity.email} has role ${user.platformRole} \u2014 only SUPER_ADMIN may use this CLI.`, 2);
|
|
79
79
|
}
|
|
80
80
|
return user;
|
|
81
81
|
}
|
|
@@ -94,7 +94,7 @@ var CliContextService = class {
|
|
|
94
94
|
}
|
|
95
95
|
const enabled = await this.mfa.isEnabled(userId);
|
|
96
96
|
if (!enabled) {
|
|
97
|
-
throw new CliError("MFA_NOT_SET_UP", "MFA
|
|
97
|
+
throw new CliError("MFA_NOT_SET_UP", "MFA is not configured. Run 'admin mfa-setup' first.", 3);
|
|
98
98
|
}
|
|
99
99
|
const code = await this.prompt("TOTP-Code: ");
|
|
100
100
|
const ok2 = await this.mfa.verify({
|
|
@@ -102,7 +102,7 @@ var CliContextService = class {
|
|
|
102
102
|
code
|
|
103
103
|
});
|
|
104
104
|
if (!ok2) {
|
|
105
|
-
throw new CliError("MFA_FAILED", "TOTP
|
|
105
|
+
throw new CliError("MFA_FAILED", "Invalid TOTP code.", 3);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
// ---------------------------------------------------------------------
|
|
@@ -111,9 +111,9 @@ var CliContextService = class {
|
|
|
111
111
|
async ensureProductionConfirmation(opts = {}) {
|
|
112
112
|
if (!this.config.isProductionEnvironment()) return;
|
|
113
113
|
if (opts.yes) return;
|
|
114
|
-
const answer = await this.prompt("
|
|
114
|
+
const answer = await this.prompt("Type production to confirm: ");
|
|
115
115
|
if (answer.trim().toLowerCase() !== "production") {
|
|
116
|
-
throw new CliError("PRODUCTION_CONFIRM_ABORTED", "Production
|
|
116
|
+
throw new CliError("PRODUCTION_CONFIRM_ABORTED", "Production confirmation aborted.", 1);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
// ---------------------------------------------------------------------
|
|
@@ -141,7 +141,7 @@ var CliContextService = class {
|
|
|
141
141
|
// ---------------------------------------------------------------------
|
|
142
142
|
table(rows) {
|
|
143
143
|
if (rows.length === 0) {
|
|
144
|
-
console.log("\u2014
|
|
144
|
+
console.log("\u2014 no entries \u2014");
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
console.table(rows);
|
|
@@ -223,9 +223,9 @@ var MfaSetupFlow = class {
|
|
|
223
223
|
const user = await this.ctx.ensureSuperAdmin(identity);
|
|
224
224
|
const alreadyEnabled = await this.mfa.isEnabled(user.id);
|
|
225
225
|
if (alreadyEnabled && !options.force) {
|
|
226
|
-
const answer = await this.ctx.prompt("MFA
|
|
226
|
+
const answer = await this.ctx.prompt("MFA is already configured. Type `yes` to overwrite the secret: ");
|
|
227
227
|
if (answer.trim().toLowerCase() !== "yes") {
|
|
228
|
-
throw new CliError("MFA_SETUP_ABORTED", "Re-
|
|
228
|
+
throw new CliError("MFA_SETUP_ABORTED", "Re-setup not confirmed \u2014 the existing secret stays active.", 1);
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
const setup = await this.mfa.setup(user.id, user.email, options.issuer);
|
|
@@ -253,15 +253,15 @@ var MfaSetupFlow = class {
|
|
|
253
253
|
*/
|
|
254
254
|
formatSetupResult(result) {
|
|
255
255
|
return [
|
|
256
|
-
`MFA
|
|
256
|
+
`MFA setup for ${result.userEmail} completed.`,
|
|
257
257
|
"",
|
|
258
258
|
`Secret (Base32): ${result.secret}`,
|
|
259
259
|
`otpauth-URI: ${result.otpauthUri}`,
|
|
260
260
|
"",
|
|
261
|
-
"
|
|
262
|
-
"1Password, \u2026)
|
|
263
|
-
"
|
|
264
|
-
"
|
|
261
|
+
"Import the otpauth URI into your authenticator (Google Authenticator,",
|
|
262
|
+
"1Password, \u2026), or render it as a QR code in a QR generator",
|
|
263
|
+
". Then verify with the first TOTP code that login",
|
|
264
|
+
"works \u2014 otherwise you will lock yourself out of the CLI."
|
|
265
265
|
].join("\n");
|
|
266
266
|
}
|
|
267
267
|
};
|
|
@@ -333,16 +333,16 @@ var WhoAmIFlow = class {
|
|
|
333
333
|
}
|
|
334
334
|
formatResult(r) {
|
|
335
335
|
const lines = [
|
|
336
|
-
`
|
|
336
|
+
`Identity: ${r.email}`,
|
|
337
337
|
`Host: ${r.host}`,
|
|
338
338
|
`Actor-Tag: ${r.actor}`,
|
|
339
|
-
`User
|
|
340
|
-
`
|
|
341
|
-
`MFA
|
|
339
|
+
`User ID: ${r.userId ?? "\u2014 (user not found)"}`,
|
|
340
|
+
`Platform role: ${r.isSuperAdmin ? "SUPER_ADMIN \u2713" : "\u2014 (not a SUPER_ADMIN!)"}`,
|
|
341
|
+
`MFA configured: ${r.mfaEnabled ? "\u2713" : "\u2717 \u2014 run `admin mfa-setup`"}`,
|
|
342
342
|
`Environment: ${r.isProduction ? "PRODUCTION" : "non-production"}`
|
|
343
343
|
];
|
|
344
344
|
if (r.mfaSkipActive) {
|
|
345
|
-
lines.push("\u26A0 MFA
|
|
345
|
+
lines.push("\u26A0 MFA bypass active (SKIP env var set, non-prod)");
|
|
346
346
|
}
|
|
347
347
|
return lines.join("\n");
|
|
348
348
|
}
|
|
@@ -478,7 +478,7 @@ var DoctorFlow = class {
|
|
|
478
478
|
}
|
|
479
479
|
formatReport(report) {
|
|
480
480
|
const lines = [
|
|
481
|
-
`Doctor
|
|
481
|
+
`Doctor check (overall status: ${report.overall.toUpperCase()})`,
|
|
482
482
|
""
|
|
483
483
|
];
|
|
484
484
|
for (const c of report.checks) {
|
|
@@ -551,62 +551,62 @@ __name(allCapabilities, "allCapabilities");
|
|
|
551
551
|
var DEFAULT_MANIFEST_CHECKS = [
|
|
552
552
|
{
|
|
553
553
|
id: "manifest.schema-version",
|
|
554
|
-
label: "schemaVersion
|
|
555
|
-
run: /* @__PURE__ */ __name((m) => m.schemaVersion === 1 ? ok("schemaVersion=1") : err(`
|
|
554
|
+
label: "schemaVersion is 1",
|
|
555
|
+
run: /* @__PURE__ */ __name((m) => m.schemaVersion === 1 ? ok("schemaVersion=1") : err(`Unexpected schemaVersion ${m.schemaVersion}`), "run")
|
|
556
556
|
},
|
|
557
557
|
{
|
|
558
558
|
id: "manifest.hash-format",
|
|
559
|
-
label: "manifestHash
|
|
559
|
+
label: "manifestHash follows the sha256-<base64url> pattern",
|
|
560
560
|
run: /* @__PURE__ */ __name((m) => {
|
|
561
561
|
const hash = m.build?.manifestHash;
|
|
562
|
-
if (!hash) return err("manifestHash
|
|
563
|
-
return /^sha256-[A-Za-z0-9_-]+$/.test(hash) ? ok(hash) : err(`manifestHash
|
|
562
|
+
if (!hash) return err("manifestHash is missing");
|
|
563
|
+
return /^sha256-[A-Za-z0-9_-]+$/.test(hash) ? ok(hash) : err(`manifestHash has the wrong format: ${hash}`);
|
|
564
564
|
}, "run")
|
|
565
565
|
},
|
|
566
566
|
{
|
|
567
567
|
id: "manifest.project-page-component-keys",
|
|
568
|
-
label: "ProjectPage.componentKey
|
|
568
|
+
label: "ProjectPage.componentKey format (lowercase-hyphenated OR namespace.dot)",
|
|
569
569
|
run: /* @__PURE__ */ __name((m) => {
|
|
570
570
|
const bad = [];
|
|
571
571
|
for (const p of allProjectPages(m)) {
|
|
572
572
|
if (!COMPONENT_KEY_PATTERN.test(p.componentKey)) bad.push(p.componentKey);
|
|
573
573
|
}
|
|
574
|
-
return bad.length === 0 ? ok(`${allProjectPages(m).length} ProjectPage(s) ok`) : err(`${bad.length} componentKey(s)
|
|
574
|
+
return bad.length === 0 ? ok(`${allProjectPages(m).length} ProjectPage(s) ok`) : err(`${bad.length} componentKey(s) violate the pattern`, bad);
|
|
575
575
|
}, "run")
|
|
576
576
|
},
|
|
577
577
|
{
|
|
578
578
|
id: "manifest.tenant-action-keys",
|
|
579
|
-
label: "TenantAction.actionKey
|
|
579
|
+
label: "TenantAction.actionKey format (domain.action \u2014 SPEC \xA74.2.1)",
|
|
580
580
|
run: /* @__PURE__ */ __name((m) => {
|
|
581
581
|
const bad = [];
|
|
582
582
|
for (const a of allTenantActions(m)) {
|
|
583
583
|
if (!TENANT_ACTION_KEY_PATTERN.test(a.actionKey)) bad.push(a.actionKey);
|
|
584
584
|
}
|
|
585
|
-
return bad.length === 0 ? ok("
|
|
585
|
+
return bad.length === 0 ? ok("every actionKey follows domain.action") : err(`${bad.length} actionKey(s) violate the pattern`, bad);
|
|
586
586
|
}, "run")
|
|
587
587
|
},
|
|
588
588
|
{
|
|
589
589
|
id: "manifest.audit-action-keys",
|
|
590
|
-
label: "AuditAction.key
|
|
590
|
+
label: "AuditAction.key format (SCREAMING_SNAKE_CASE)",
|
|
591
591
|
run: /* @__PURE__ */ __name((m) => {
|
|
592
592
|
const bad = [];
|
|
593
593
|
for (const a of allAuditActions(m)) {
|
|
594
594
|
if (!ACTION_KEY_PATTERN.test(a.key)) bad.push(a.key);
|
|
595
595
|
}
|
|
596
|
-
return bad.length === 0 ? ok("
|
|
596
|
+
return bad.length === 0 ? ok("every AuditAction.key is SCREAMING_SNAKE_CASE") : err(`${bad.length} AuditAction.key(s) violate the pattern`, bad);
|
|
597
597
|
}, "run")
|
|
598
598
|
},
|
|
599
599
|
{
|
|
600
600
|
id: "manifest.capabilities-pattern",
|
|
601
|
-
label: "Capability
|
|
601
|
+
label: "Capability pattern <domain>.<action> (SPEC \xA74.2.1)",
|
|
602
602
|
run: /* @__PURE__ */ __name((m) => {
|
|
603
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
|
|
604
|
+
return bad.length === 0 ? ok(`${allCapabilities(m).length} Capabilities ok`) : err(`${bad.length} Capability/-ies violate the pattern`, bad);
|
|
605
605
|
}, "run")
|
|
606
606
|
},
|
|
607
607
|
{
|
|
608
608
|
id: "manifest.required-capabilities-known",
|
|
609
|
-
label: "requiredCapability
|
|
609
|
+
label: "requiredCapability references resolve against the capabilities map",
|
|
610
610
|
run: /* @__PURE__ */ __name((m) => {
|
|
611
611
|
const known = new Set(allCapabilities(m));
|
|
612
612
|
const bad = [];
|
|
@@ -617,23 +617,23 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
617
617
|
for (const k of allKpiCards(m)) visit(k.requiredCapability, k.id);
|
|
618
618
|
for (const a of allTenantActions(m)) visit(a.requiredCapability, a.id);
|
|
619
619
|
for (const c of allTenantColumns(m)) visit(c.requiredCapability, c.key);
|
|
620
|
-
return bad.length === 0 ? ok("
|
|
620
|
+
return bad.length === 0 ? ok("every requiredCapability ref resolves") : err(`${bad.length} unknown capability ref(s)`, bad);
|
|
621
621
|
}, "run")
|
|
622
622
|
},
|
|
623
623
|
{
|
|
624
624
|
id: "manifest.route-prefix",
|
|
625
|
-
label: "ProjectPage.route
|
|
625
|
+
label: "ProjectPage.route starts with /admin",
|
|
626
626
|
run: /* @__PURE__ */ __name((m) => {
|
|
627
627
|
const bad = [];
|
|
628
628
|
for (const p of allProjectPages(m)) {
|
|
629
629
|
if (!p.route.startsWith(ROUTE_PREFIX)) bad.push(p.route);
|
|
630
630
|
}
|
|
631
|
-
return bad.length === 0 ? ok("
|
|
631
|
+
return bad.length === 0 ? ok("every ProjectPage route is under /admin") : err(`${bad.length} route(s) without the /admin prefix`, bad);
|
|
632
632
|
}, "run")
|
|
633
633
|
},
|
|
634
634
|
{
|
|
635
635
|
id: "manifest.kpi-slot-priority",
|
|
636
|
-
label: "KpiCard.slotPriority (
|
|
636
|
+
label: "KpiCard.slotPriority (if set) is a finite number",
|
|
637
637
|
run: /* @__PURE__ */ __name((m) => {
|
|
638
638
|
const bad = [];
|
|
639
639
|
for (const k of allKpiCards(m)) {
|
|
@@ -641,12 +641,12 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
641
641
|
bad.push(k.id);
|
|
642
642
|
}
|
|
643
643
|
}
|
|
644
|
-
return bad.length === 0 ? ok("
|
|
644
|
+
return bad.length === 0 ? ok("every slotPriority value is finite") : err(`${bad.length} KpiCard(s) with an invalid slotPriority`, bad);
|
|
645
645
|
}, "run")
|
|
646
646
|
},
|
|
647
647
|
{
|
|
648
648
|
id: "manifest.unique-project-page-ids",
|
|
649
|
-
label: "ProjectPage.id
|
|
649
|
+
label: "ProjectPage.id is unique",
|
|
650
650
|
run: /* @__PURE__ */ __name((m) => {
|
|
651
651
|
const seen = /* @__PURE__ */ new Map();
|
|
652
652
|
for (const p of allProjectPages(m)) {
|
|
@@ -655,12 +655,12 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
655
655
|
const dups = [
|
|
656
656
|
...seen.entries()
|
|
657
657
|
].filter(([, n]) => n > 1).map(([k]) => k);
|
|
658
|
-
return dups.length === 0 ? ok("
|
|
658
|
+
return dups.length === 0 ? ok("every ProjectPage.id is unique") : err(`${dups.length} duplicate ProjectPage.id(s)`, dups);
|
|
659
659
|
}, "run")
|
|
660
660
|
},
|
|
661
661
|
{
|
|
662
662
|
id: "manifest.unique-action-keys",
|
|
663
|
-
label: "actionKeys
|
|
663
|
+
label: "actionKeys are unique per namespace (TenantAction / AuditAction)",
|
|
664
664
|
run: /* @__PURE__ */ __name((m) => {
|
|
665
665
|
const dups = [];
|
|
666
666
|
const tenantSeen = /* @__PURE__ */ new Map();
|
|
@@ -677,21 +677,21 @@ var DEFAULT_MANIFEST_CHECKS = [
|
|
|
677
677
|
for (const [k, n] of auditSeen) {
|
|
678
678
|
if (n > 1) dups.push(`AuditAction:${k}`);
|
|
679
679
|
}
|
|
680
|
-
return dups.length === 0 ? ok("
|
|
680
|
+
return dups.length === 0 ? ok("every actionKey is unique per namespace") : err(`${dups.length} duplicate actionKey(s)`, dups);
|
|
681
681
|
}, "run")
|
|
682
682
|
},
|
|
683
683
|
{
|
|
684
684
|
id: "manifest.tenant-columns-batchable",
|
|
685
|
-
label: "
|
|
685
|
+
label: "tenant columns carry an endpoint path for batch fetching",
|
|
686
686
|
run: /* @__PURE__ */ __name((m) => {
|
|
687
687
|
const bad = [];
|
|
688
688
|
for (const c of allTenantColumns(m)) {
|
|
689
689
|
if (!c.endpoint || c.endpoint.trim().length === 0) bad.push(c.key);
|
|
690
690
|
else if (c.endpoint.includes("{slug}") || c.endpoint.includes("{tenantId}")) {
|
|
691
|
-
bad.push(`${c.key} (per-
|
|
691
|
+
bad.push(`${c.key} (per-tenant instead of batch)`);
|
|
692
692
|
}
|
|
693
693
|
}
|
|
694
|
-
return bad.length === 0 ? ok("
|
|
694
|
+
return bad.length === 0 ? ok("every tenant column supports batch fetching") : err(`${bad.length} TenantColumn(s) violate the batch requirement`, bad);
|
|
695
695
|
}, "run")
|
|
696
696
|
}
|
|
697
697
|
];
|
|
@@ -737,7 +737,7 @@ var ManifestCliFlow = class {
|
|
|
737
737
|
hash() {
|
|
738
738
|
const m = this.access.getManifest();
|
|
739
739
|
const h = m.build?.manifestHash;
|
|
740
|
-
if (!h) throw new Error("manifestHash
|
|
740
|
+
if (!h) throw new Error("manifestHash is missing from the manifest \u2014 a boot-time bug?");
|
|
741
741
|
return h;
|
|
742
742
|
}
|
|
743
743
|
/**
|
|
@@ -751,19 +751,19 @@ var ManifestCliFlow = class {
|
|
|
751
751
|
if (m.schemaVersion !== 1) {
|
|
752
752
|
return {
|
|
753
753
|
ok: false,
|
|
754
|
-
reason: `
|
|
754
|
+
reason: `Unexpected schemaVersion ${m.schemaVersion}`
|
|
755
755
|
};
|
|
756
756
|
}
|
|
757
757
|
if (!m.project?.key) {
|
|
758
758
|
return {
|
|
759
759
|
ok: false,
|
|
760
|
-
reason: "
|
|
760
|
+
reason: "No `project.key` in the manifest"
|
|
761
761
|
};
|
|
762
762
|
}
|
|
763
763
|
if (!m.build?.manifestHash) {
|
|
764
764
|
return {
|
|
765
765
|
ok: false,
|
|
766
|
-
reason: "manifestHash
|
|
766
|
+
reason: "manifestHash is missing"
|
|
767
767
|
};
|
|
768
768
|
}
|
|
769
769
|
return {
|
|
@@ -815,7 +815,7 @@ var ManifestCliFlow = class {
|
|
|
815
815
|
id: check.id,
|
|
816
816
|
label: check.label,
|
|
817
817
|
severity: "error",
|
|
818
|
-
message: `
|
|
818
|
+
message: `The check threw an exception: ${message}`
|
|
819
819
|
});
|
|
820
820
|
overall = "error";
|
|
821
821
|
}
|
|
@@ -831,7 +831,7 @@ var ManifestCliFlow = class {
|
|
|
831
831
|
}
|
|
832
832
|
formatReport(report) {
|
|
833
833
|
const lines = [
|
|
834
|
-
`Manifest
|
|
834
|
+
`Manifest check (overall status: ${report.overall.toUpperCase()})`,
|
|
835
835
|
""
|
|
836
836
|
];
|
|
837
837
|
for (const c of report.checks) {
|
|
@@ -893,7 +893,7 @@ var PlanCatalogDoctorCheck = class {
|
|
|
893
893
|
}
|
|
894
894
|
catalog;
|
|
895
895
|
id = "platform.plan-catalog";
|
|
896
|
-
label = "Plan
|
|
896
|
+
label = "Plan catalog in DI";
|
|
897
897
|
constructor(catalog) {
|
|
898
898
|
this.catalog = catalog;
|
|
899
899
|
}
|
|
@@ -902,12 +902,12 @@ var PlanCatalogDoctorCheck = class {
|
|
|
902
902
|
if (plans.length === 0) {
|
|
903
903
|
return {
|
|
904
904
|
severity: "error",
|
|
905
|
-
message: "
|
|
905
|
+
message: "The plan catalog contains no plans \u2014 the onboarding pricing page will be empty."
|
|
906
906
|
};
|
|
907
907
|
}
|
|
908
908
|
return {
|
|
909
909
|
severity: "ok",
|
|
910
|
-
message: `${plans.length}
|
|
910
|
+
message: `${plans.length} plan(s), ${this.catalog.features?.length ?? 0} feature(s) loaded.`,
|
|
911
911
|
details: {
|
|
912
912
|
projectKey: this.catalog.projectKey,
|
|
913
913
|
planIds: plans.map((p) => p.id)
|
|
@@ -929,7 +929,7 @@ var DiscoverySnapshotDoctorCheck = class {
|
|
|
929
929
|
}
|
|
930
930
|
snapshot;
|
|
931
931
|
id = "platform.discovery-snapshot";
|
|
932
|
-
label = "Discovery
|
|
932
|
+
label = "Discovery snapshot on boot";
|
|
933
933
|
constructor(snapshot) {
|
|
934
934
|
this.snapshot = snapshot;
|
|
935
935
|
}
|
|
@@ -938,7 +938,7 @@ var DiscoverySnapshotDoctorCheck = class {
|
|
|
938
938
|
if (caps.length === 0) {
|
|
939
939
|
return {
|
|
940
940
|
severity: "warning",
|
|
941
|
-
message: "
|
|
941
|
+
message: "No capabilities discovered \u2014 decorator-carrying modules may be missing from AppModule.imports[]."
|
|
942
942
|
};
|
|
943
943
|
}
|
|
944
944
|
return {
|
|
@@ -961,7 +961,7 @@ var UserPortDoctorCheck = class {
|
|
|
961
961
|
}
|
|
962
962
|
users;
|
|
963
963
|
id = "platform.user-port";
|
|
964
|
-
label = "UserPort.findByEmail
|
|
964
|
+
label = "UserPort.findByEmail reachable";
|
|
965
965
|
constructor(users) {
|
|
966
966
|
this.users = users;
|
|
967
967
|
}
|
|
@@ -970,12 +970,12 @@ var UserPortDoctorCheck = class {
|
|
|
970
970
|
await this.users.findByEmail("__doctor-check__@invalid.local");
|
|
971
971
|
return {
|
|
972
972
|
severity: "ok",
|
|
973
|
-
message: "UserPort
|
|
973
|
+
message: "UserPort responds."
|
|
974
974
|
};
|
|
975
975
|
} catch (err2) {
|
|
976
976
|
return {
|
|
977
977
|
severity: "error",
|
|
978
|
-
message: `UserPort
|
|
978
|
+
message: `UserPort throws: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
979
979
|
};
|
|
980
980
|
}
|
|
981
981
|
}
|
|
@@ -994,7 +994,7 @@ var AdminManifestDoctorCheck = class {
|
|
|
994
994
|
}
|
|
995
995
|
manifest;
|
|
996
996
|
id = "platform.admin-manifest";
|
|
997
|
-
label = "AdminManifestService
|
|
997
|
+
label = "AdminManifestService returns a manifest";
|
|
998
998
|
constructor(manifest) {
|
|
999
999
|
this.manifest = manifest;
|
|
1000
1000
|
}
|
|
@@ -1004,12 +1004,12 @@ var AdminManifestDoctorCheck = class {
|
|
|
1004
1004
|
const pageCount = Object.keys(m.navigation?.standardPages ?? {}).length;
|
|
1005
1005
|
return {
|
|
1006
1006
|
severity: "ok",
|
|
1007
|
-
message: `Manifest
|
|
1007
|
+
message: `Manifest with ${pageCount} standard pages, hash ${m.build?.manifestHash?.slice(0, 12) ?? "???"}\u2026`
|
|
1008
1008
|
};
|
|
1009
1009
|
} catch (err2) {
|
|
1010
1010
|
return {
|
|
1011
1011
|
severity: "error",
|
|
1012
|
-
message: `Manifest
|
|
1012
|
+
message: `Manifest build throws: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
1013
1013
|
};
|
|
1014
1014
|
}
|
|
1015
1015
|
}
|
|
@@ -1152,11 +1152,11 @@ function applyFragmentBlocks(schema, fragmentBlocks, options = {}) {
|
|
|
1152
1152
|
const header = options.fragmentLabel ? `
|
|
1153
1153
|
|
|
1154
1154
|
// ============================================================
|
|
1155
|
-
//
|
|
1155
|
+
// Inserted by \`saasicat schema apply\` from ${options.fragmentLabel}
|
|
1156
1156
|
// ============================================================
|
|
1157
1157
|
` : `
|
|
1158
1158
|
|
|
1159
|
-
//
|
|
1159
|
+
// Inserted by \`saasicat schema apply\`
|
|
1160
1160
|
`;
|
|
1161
1161
|
const trimmedSchema = schema.endsWith("\n") ? schema : schema + "\n";
|
|
1162
1162
|
return {
|
|
@@ -1470,7 +1470,7 @@ ManifestDumpCommand = _ts_decorate9([
|
|
|
1470
1470
|
Injectable8(),
|
|
1471
1471
|
SubCommand({
|
|
1472
1472
|
name: "dump",
|
|
1473
|
-
description: "
|
|
1473
|
+
description: "Print the manifest as JSON"
|
|
1474
1474
|
}),
|
|
1475
1475
|
_ts_metadata8("design:type", Function),
|
|
1476
1476
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1510,7 +1510,7 @@ ManifestHashCommand = _ts_decorate9([
|
|
|
1510
1510
|
Injectable8(),
|
|
1511
1511
|
SubCommand({
|
|
1512
1512
|
name: "hash",
|
|
1513
|
-
description: "manifestHash
|
|
1513
|
+
description: "Print the manifestHash (CI pinning)"
|
|
1514
1514
|
}),
|
|
1515
1515
|
_ts_metadata8("design:type", Function),
|
|
1516
1516
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1532,7 +1532,7 @@ var ManifestValidateCommand = class extends CommandRunner {
|
|
|
1532
1532
|
await this.ctx.ensureSuperAdmin(identity);
|
|
1533
1533
|
const result = this.flow.validate();
|
|
1534
1534
|
if (result.ok) {
|
|
1535
|
-
process.stdout.write("Manifest
|
|
1535
|
+
process.stdout.write("Manifest is valid \u2713\n");
|
|
1536
1536
|
return;
|
|
1537
1537
|
}
|
|
1538
1538
|
process.stderr.write(`Manifest invalid: ${result.reason}
|
|
@@ -1557,7 +1557,7 @@ ManifestValidateCommand = _ts_decorate9([
|
|
|
1557
1557
|
Injectable8(),
|
|
1558
1558
|
SubCommand({
|
|
1559
1559
|
name: "validate",
|
|
1560
|
-
description: "
|
|
1560
|
+
description: "Quick sanity check (schemaVersion + project.key + manifestHash)"
|
|
1561
1561
|
}),
|
|
1562
1562
|
_ts_metadata8("design:type", Function),
|
|
1563
1563
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1600,7 +1600,7 @@ ManifestCheckCommand = _ts_decorate9([
|
|
|
1600
1600
|
Injectable8(),
|
|
1601
1601
|
SubCommand({
|
|
1602
1602
|
name: "check",
|
|
1603
|
-
description: "
|
|
1603
|
+
description: "All manifest checks (exit code 7 on error/drift)"
|
|
1604
1604
|
}),
|
|
1605
1605
|
_ts_metadata8("design:type", Function),
|
|
1606
1606
|
_ts_metadata8("design:paramtypes", [
|
|
@@ -1613,7 +1613,7 @@ var ManifestCommands = class extends CommandRunner {
|
|
|
1613
1613
|
__name(this, "ManifestCommands");
|
|
1614
1614
|
}
|
|
1615
1615
|
async run() {
|
|
1616
|
-
process.stderr.write("
|
|
1616
|
+
process.stderr.write("Specify a sub-command: dump, hash, validate, check.\n");
|
|
1617
1617
|
process.exit(2);
|
|
1618
1618
|
}
|
|
1619
1619
|
};
|
|
@@ -1621,7 +1621,7 @@ ManifestCommands = _ts_decorate9([
|
|
|
1621
1621
|
Injectable8(),
|
|
1622
1622
|
Command({
|
|
1623
1623
|
name: "manifest",
|
|
1624
|
-
description: "Manifest
|
|
1624
|
+
description: "Manifest operations (dump, hash, validate, check)",
|
|
1625
1625
|
subCommands: [
|
|
1626
1626
|
ManifestDumpCommand,
|
|
1627
1627
|
ManifestHashCommand,
|
|
@@ -1682,7 +1682,7 @@ AdminWhoamiCommand = _ts_decorate10([
|
|
|
1682
1682
|
Injectable9(),
|
|
1683
1683
|
SubCommand2({
|
|
1684
1684
|
name: "whoami",
|
|
1685
|
-
description: "
|
|
1685
|
+
description: "Active CLI identity plus MFA and production status"
|
|
1686
1686
|
}),
|
|
1687
1687
|
_ts_metadata9("design:type", Function),
|
|
1688
1688
|
_ts_metadata9("design:paramtypes", [
|
|
@@ -1734,7 +1734,7 @@ _ts_decorate10([
|
|
|
1734
1734
|
_ts_decorate10([
|
|
1735
1735
|
Option2({
|
|
1736
1736
|
flags: "--force",
|
|
1737
|
-
description: "
|
|
1737
|
+
description: "overwrite an existing secret without asking"
|
|
1738
1738
|
}),
|
|
1739
1739
|
_ts_metadata9("design:type", Function),
|
|
1740
1740
|
_ts_metadata9("design:paramtypes", []),
|
|
@@ -1744,7 +1744,7 @@ AdminMfaSetupCommand = _ts_decorate10([
|
|
|
1744
1744
|
Injectable9(),
|
|
1745
1745
|
SubCommand2({
|
|
1746
1746
|
name: "mfa-setup",
|
|
1747
|
-
description: "TOTP
|
|
1747
|
+
description: "Set up TOTP MFA for your own super-admin account"
|
|
1748
1748
|
}),
|
|
1749
1749
|
_ts_param7(0, Inject7(CLI_CONTEXT_CONFIG_TOKEN)),
|
|
1750
1750
|
_ts_metadata9("design:type", Function),
|
|
@@ -1758,7 +1758,7 @@ var AdminCommands = class extends CommandRunner2 {
|
|
|
1758
1758
|
__name(this, "AdminCommands");
|
|
1759
1759
|
}
|
|
1760
1760
|
async run() {
|
|
1761
|
-
process.stderr.write("
|
|
1761
|
+
process.stderr.write("Specify a sub-command: whoami, mfa-setup.\n");
|
|
1762
1762
|
process.exit(2);
|
|
1763
1763
|
}
|
|
1764
1764
|
};
|
|
@@ -1892,7 +1892,7 @@ AuditTailCommand = _ts_decorate11([
|
|
|
1892
1892
|
Injectable10(),
|
|
1893
1893
|
SubCommand3({
|
|
1894
1894
|
name: "tail",
|
|
1895
|
-
description: "
|
|
1895
|
+
description: "Most recent audit-log entries (--actor/--action/--entity/--since/--limit)"
|
|
1896
1896
|
}),
|
|
1897
1897
|
_ts_metadata10("design:type", Function),
|
|
1898
1898
|
_ts_metadata10("design:paramtypes", [
|
|
@@ -1905,7 +1905,7 @@ var AuditCommands = class extends CommandRunner3 {
|
|
|
1905
1905
|
__name(this, "AuditCommands");
|
|
1906
1906
|
}
|
|
1907
1907
|
async run() {
|
|
1908
|
-
process.stderr.write("
|
|
1908
|
+
process.stderr.write("Specify a sub-command: tail.\n");
|
|
1909
1909
|
process.exit(2);
|
|
1910
1910
|
}
|
|
1911
1911
|
};
|
|
@@ -1969,7 +1969,7 @@ DoctorCommands = _ts_decorate12([
|
|
|
1969
1969
|
Injectable11(),
|
|
1970
1970
|
Command4({
|
|
1971
1971
|
name: "doctor",
|
|
1972
|
-
description: "Health
|
|
1972
|
+
description: "Health/drift checks (exit code 4 on error)"
|
|
1973
1973
|
}),
|
|
1974
1974
|
_ts_metadata11("design:type", Function),
|
|
1975
1975
|
_ts_metadata11("design:paramtypes", [
|
|
@@ -2012,7 +2012,7 @@ var DiscoveryScanCommand = class extends CommandRunner5 {
|
|
|
2012
2012
|
}
|
|
2013
2013
|
async run(_args, flags) {
|
|
2014
2014
|
if (!this.scanner) {
|
|
2015
|
-
this.fail("DiscoveryScanner
|
|
2015
|
+
this.fail("DiscoveryScanner is not registered \u2014 import DiscoveryModule.forRoot() in the CLI module.", flags);
|
|
2016
2016
|
return;
|
|
2017
2017
|
}
|
|
2018
2018
|
try {
|
|
@@ -2028,10 +2028,10 @@ var DiscoveryScanCommand = class extends CommandRunner5 {
|
|
|
2028
2028
|
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
|
|
2029
2029
|
`);
|
|
2030
2030
|
if (target) {
|
|
2031
|
-
process.stdout.write(`Snapshot
|
|
2031
|
+
process.stdout.write(`Snapshot persisted: ${resolvePath(target)}
|
|
2032
2032
|
`);
|
|
2033
2033
|
} else {
|
|
2034
|
-
process.stderr.write("
|
|
2034
|
+
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");
|
|
2035
2035
|
}
|
|
2036
2036
|
} catch (err2) {
|
|
2037
2037
|
this.fail(err2 instanceof Error ? err2.message : String(err2), flags);
|
|
@@ -2044,7 +2044,7 @@ var DiscoveryScanCommand = class extends CommandRunner5 {
|
|
|
2044
2044
|
`);
|
|
2045
2045
|
return;
|
|
2046
2046
|
}
|
|
2047
|
-
process.stderr.write(`[discovery scan]
|
|
2047
|
+
process.stderr.write(`[discovery scan] ERROR: ${message}
|
|
2048
2048
|
`);
|
|
2049
2049
|
process.exit(4);
|
|
2050
2050
|
}
|
|
@@ -2058,7 +2058,7 @@ var DiscoveryScanCommand = class extends CommandRunner5 {
|
|
|
2058
2058
|
_ts_decorate13([
|
|
2059
2059
|
Option5({
|
|
2060
2060
|
flags: "--out <path>",
|
|
2061
|
-
description: "
|
|
2061
|
+
description: "Additionally write the snapshot to this path"
|
|
2062
2062
|
}),
|
|
2063
2063
|
_ts_metadata12("design:type", Function),
|
|
2064
2064
|
_ts_metadata12("design:paramtypes", [
|
|
@@ -2069,7 +2069,7 @@ _ts_decorate13([
|
|
|
2069
2069
|
_ts_decorate13([
|
|
2070
2070
|
Option5({
|
|
2071
2071
|
flags: "--non-fatal",
|
|
2072
|
-
description: "
|
|
2072
|
+
description: "Report scan errors as a warning only (exit 0) \u2014 staged rollout"
|
|
2073
2073
|
}),
|
|
2074
2074
|
_ts_metadata12("design:type", Function),
|
|
2075
2075
|
_ts_metadata12("design:paramtypes", []),
|
|
@@ -2079,7 +2079,7 @@ DiscoveryScanCommand = _ts_decorate13([
|
|
|
2079
2079
|
Injectable12(),
|
|
2080
2080
|
SubCommand4({
|
|
2081
2081
|
name: "scan",
|
|
2082
|
-
description: "
|
|
2082
|
+
description: "Produce and persist a discovery snapshot headlessly (seed gate, #23)"
|
|
2083
2083
|
}),
|
|
2084
2084
|
_ts_param8(0, Optional()),
|
|
2085
2085
|
_ts_param8(0, Inject8(DiscoveryScanner)),
|
|
@@ -2096,7 +2096,7 @@ var DiscoveryCommands = class extends CommandRunner5 {
|
|
|
2096
2096
|
__name(this, "DiscoveryCommands");
|
|
2097
2097
|
}
|
|
2098
2098
|
async run() {
|
|
2099
|
-
process.stderr.write("
|
|
2099
|
+
process.stderr.write("Specify a sub-command: scan.\n");
|
|
2100
2100
|
process.exit(2);
|
|
2101
2101
|
}
|
|
2102
2102
|
};
|
|
@@ -2162,12 +2162,12 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2162
2162
|
case "deactivate":
|
|
2163
2163
|
return this.deactivate(args[1], flags, identity, me.id);
|
|
2164
2164
|
default:
|
|
2165
|
-
throw new CliError("UNKNOWN_SUBCOMMAND", `
|
|
2165
|
+
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);
|
|
2166
2166
|
}
|
|
2167
2167
|
}
|
|
2168
2168
|
async createSuperAdmin(email, flags, identity, meId, meEmail) {
|
|
2169
2169
|
if (!email) {
|
|
2170
|
-
throw new CliError("MISSING_ARG", "user create-super-admin <email>
|
|
2170
|
+
throw new CliError("MISSING_ARG", "user create-super-admin <email> expects an email address.", 1);
|
|
2171
2171
|
}
|
|
2172
2172
|
await this.ctx.requireMfa(meId);
|
|
2173
2173
|
await this.ctx.ensureProductionConfirmation({
|
|
@@ -2192,20 +2192,20 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2192
2192
|
createdBy: meEmail
|
|
2193
2193
|
}
|
|
2194
2194
|
});
|
|
2195
|
-
console.log(`\u2714 SUPER_ADMIN ${created.email}
|
|
2195
|
+
console.log(`\u2714 SUPER_ADMIN ${created.email} created (by ${meEmail}).`);
|
|
2196
2196
|
console.log(` User-ID: ${created.id}`);
|
|
2197
2197
|
if (generated) {
|
|
2198
|
-
console.log(`
|
|
2199
|
-
console.log(" \u2192
|
|
2198
|
+
console.log(` Password: ${password}`);
|
|
2199
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2200
2200
|
}
|
|
2201
|
-
console.log(`
|
|
2201
|
+
console.log(` Next step: admin mfa-setup for ${created.email}.`);
|
|
2202
2202
|
}
|
|
2203
2203
|
async reassignAdmin(slug, flags, identity, meId) {
|
|
2204
2204
|
if (!slug) {
|
|
2205
|
-
throw new CliError("MISSING_ARG", "user reassign-admin <tenant-slug>
|
|
2205
|
+
throw new CliError("MISSING_ARG", "user reassign-admin <tenant-slug> expects a slug.", 1);
|
|
2206
2206
|
}
|
|
2207
|
-
if (!flags.to) throw new CliError("MISSING_FLAG", "--to=<email>
|
|
2208
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2207
|
+
if (!flags.to) throw new CliError("MISSING_FLAG", "--to=<email> is required.", 1);
|
|
2208
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2209
2209
|
await this.ctx.requireMfa(meId);
|
|
2210
2210
|
const result = await this.users.reassignTenantAdmin(slug, flags.to.toLowerCase());
|
|
2211
2211
|
await this.ctx.log({
|
|
@@ -2223,18 +2223,18 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2223
2223
|
}
|
|
2224
2224
|
});
|
|
2225
2225
|
if (result.created) {
|
|
2226
|
-
console.log(`\u2714
|
|
2226
|
+
console.log(`\u2714 Emergency admin ${result.user.email} created for ${slug}.`);
|
|
2227
2227
|
if (result.oneTimePassword) {
|
|
2228
|
-
console.log(` Initial
|
|
2229
|
-
console.log(" \u2192
|
|
2228
|
+
console.log(` Initial password: ${result.oneTimePassword}`);
|
|
2229
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2230
2230
|
}
|
|
2231
2231
|
} else {
|
|
2232
|
-
console.log(`\u2714 ${result.user.email}
|
|
2232
|
+
console.log(`\u2714 ${result.user.email} is now TENANT_ADMIN of ${slug}.`);
|
|
2233
2233
|
}
|
|
2234
2234
|
}
|
|
2235
2235
|
async list(slug) {
|
|
2236
2236
|
if (!slug) {
|
|
2237
|
-
throw new CliError("MISSING_ARG", "user list <tenant-slug>
|
|
2237
|
+
throw new CliError("MISSING_ARG", "user list <tenant-slug> expects a slug.", 1);
|
|
2238
2238
|
}
|
|
2239
2239
|
const rows = await this.users.listTenantUsers(slug);
|
|
2240
2240
|
this.ctx.table(rows.map((u) => ({
|
|
@@ -2246,9 +2246,9 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2246
2246
|
}
|
|
2247
2247
|
async resetPassword(email, flags, identity, meId) {
|
|
2248
2248
|
if (!email) {
|
|
2249
|
-
throw new CliError("MISSING_ARG", "user reset-password <email>
|
|
2249
|
+
throw new CliError("MISSING_ARG", "user reset-password <email> expects an email address.", 1);
|
|
2250
2250
|
}
|
|
2251
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2251
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2252
2252
|
const result = await this.users.triggerPasswordReset(email.toLowerCase());
|
|
2253
2253
|
await this.ctx.log({
|
|
2254
2254
|
identity,
|
|
@@ -2261,18 +2261,18 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2261
2261
|
}
|
|
2262
2262
|
});
|
|
2263
2263
|
if (result.oneTimePassword) {
|
|
2264
|
-
console.log(`\u2714
|
|
2265
|
-
console.log(`
|
|
2266
|
-
console.log(" \u2192
|
|
2264
|
+
console.log(`\u2714 One-time password set for ${result.user.email}.`);
|
|
2265
|
+
console.log(` Password: ${result.oneTimePassword}`);
|
|
2266
|
+
console.log(" \u2192 Share it securely. Change it on first login.");
|
|
2267
2267
|
} else {
|
|
2268
|
-
console.log(`\u2714
|
|
2268
|
+
console.log(`\u2714 Password reset triggered for ${result.user.email}.`);
|
|
2269
2269
|
}
|
|
2270
2270
|
}
|
|
2271
2271
|
async deactivate(email, flags, identity, meId) {
|
|
2272
2272
|
if (!email) {
|
|
2273
|
-
throw new CliError("MISSING_ARG", "user deactivate <email>
|
|
2273
|
+
throw new CliError("MISSING_ARG", "user deactivate <email> expects an email address.", 1);
|
|
2274
2274
|
}
|
|
2275
|
-
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026"
|
|
2275
|
+
if (!flags.reason) throw new CliError("MISSING_FLAG", '--reason="\u2026" is required.', 1);
|
|
2276
2276
|
await this.ctx.requireMfa(meId);
|
|
2277
2277
|
await this.ctx.ensureProductionConfirmation({
|
|
2278
2278
|
yes: flags.yes
|
|
@@ -2289,7 +2289,7 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2289
2289
|
emergency: true
|
|
2290
2290
|
}
|
|
2291
2291
|
});
|
|
2292
|
-
console.log(`\u2714 ${user.email}
|
|
2292
|
+
console.log(`\u2714 ${user.email} deactivated.`);
|
|
2293
2293
|
}
|
|
2294
2294
|
parseAs(val) {
|
|
2295
2295
|
return val;
|
|
@@ -2316,7 +2316,7 @@ var UserCommands = class extends CommandRunner6 {
|
|
|
2316
2316
|
_ts_decorate14([
|
|
2317
2317
|
Option6({
|
|
2318
2318
|
flags: "--as <email>",
|
|
2319
|
-
description: "CLI
|
|
2319
|
+
description: "CLI identity (otherwise <APP>_ADMIN_EMAIL)"
|
|
2320
2320
|
}),
|
|
2321
2321
|
_ts_metadata13("design:type", Function),
|
|
2322
2322
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2327,7 +2327,7 @@ _ts_decorate14([
|
|
|
2327
2327
|
_ts_decorate14([
|
|
2328
2328
|
Option6({
|
|
2329
2329
|
flags: "--to <email>",
|
|
2330
|
-
description: "
|
|
2330
|
+
description: "Target user (reassign-admin)"
|
|
2331
2331
|
}),
|
|
2332
2332
|
_ts_metadata13("design:type", Function),
|
|
2333
2333
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2338,7 +2338,7 @@ _ts_decorate14([
|
|
|
2338
2338
|
_ts_decorate14([
|
|
2339
2339
|
Option6({
|
|
2340
2340
|
flags: "--reason <text>",
|
|
2341
|
-
description: "
|
|
2341
|
+
description: "Reason (audit)"
|
|
2342
2342
|
}),
|
|
2343
2343
|
_ts_metadata13("design:type", Function),
|
|
2344
2344
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2349,7 +2349,7 @@ _ts_decorate14([
|
|
|
2349
2349
|
_ts_decorate14([
|
|
2350
2350
|
Option6({
|
|
2351
2351
|
flags: "-y, --yes",
|
|
2352
|
-
description: "
|
|
2352
|
+
description: "Skip the production confirmation"
|
|
2353
2353
|
}),
|
|
2354
2354
|
_ts_metadata13("design:type", Function),
|
|
2355
2355
|
_ts_metadata13("design:paramtypes", []),
|
|
@@ -2358,7 +2358,7 @@ _ts_decorate14([
|
|
|
2358
2358
|
_ts_decorate14([
|
|
2359
2359
|
Option6({
|
|
2360
2360
|
flags: "--first <name>",
|
|
2361
|
-
description: "
|
|
2361
|
+
description: "First name (create-super-admin)"
|
|
2362
2362
|
}),
|
|
2363
2363
|
_ts_metadata13("design:type", Function),
|
|
2364
2364
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2369,7 +2369,7 @@ _ts_decorate14([
|
|
|
2369
2369
|
_ts_decorate14([
|
|
2370
2370
|
Option6({
|
|
2371
2371
|
flags: "--last <name>",
|
|
2372
|
-
description: "
|
|
2372
|
+
description: "Last name (create-super-admin)"
|
|
2373
2373
|
}),
|
|
2374
2374
|
_ts_metadata13("design:type", Function),
|
|
2375
2375
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2380,7 +2380,7 @@ _ts_decorate14([
|
|
|
2380
2380
|
_ts_decorate14([
|
|
2381
2381
|
Option6({
|
|
2382
2382
|
flags: "--password <pwd>",
|
|
2383
|
-
description: "
|
|
2383
|
+
description: "Password (create-super-admin; generated when omitted)"
|
|
2384
2384
|
}),
|
|
2385
2385
|
_ts_metadata13("design:type", Function),
|
|
2386
2386
|
_ts_metadata13("design:paramtypes", [
|
|
@@ -2392,7 +2392,7 @@ UserCommands = _ts_decorate14([
|
|
|
2392
2392
|
Injectable13(),
|
|
2393
2393
|
Command6({
|
|
2394
2394
|
name: "user",
|
|
2395
|
-
description: "User
|
|
2395
|
+
description: "User operations (create-super-admin, reassign-admin, list, reset-password, deactivate)"
|
|
2396
2396
|
}),
|
|
2397
2397
|
_ts_param9(1, Inject9(USER_MANAGEMENT_PORT_TOKEN)),
|
|
2398
2398
|
_ts_metadata13("design:type", Function),
|