@treeseed/cli 0.8.1 → 0.8.2
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,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatTreeseedHostingAuditReport,
|
|
3
|
+
runTreeseedHostingAudit
|
|
4
|
+
} from "@treeseed/sdk/workflow-support";
|
|
5
|
+
import { guidedResult } from "./utils.js";
|
|
6
|
+
import { workflowErrorResult } from "./workflow.js";
|
|
7
|
+
const ENVIRONMENTS = /* @__PURE__ */ new Set(["current", "local", "staging", "prod"]);
|
|
8
|
+
const HOST_KINDS = /* @__PURE__ */ new Set(["repository", "web", "processing", "email"]);
|
|
9
|
+
function normalizeEnvironment(value) {
|
|
10
|
+
const environment = typeof value === "string" && value.trim() ? value.trim() : "current";
|
|
11
|
+
if (!ENVIRONMENTS.has(environment)) {
|
|
12
|
+
throw new Error(`Unsupported audit environment "${environment}". Expected current, local, staging, or prod.`);
|
|
13
|
+
}
|
|
14
|
+
return environment;
|
|
15
|
+
}
|
|
16
|
+
function normalizeHostKinds(value) {
|
|
17
|
+
if (value === void 0 || value === null || value === "") {
|
|
18
|
+
return void 0;
|
|
19
|
+
}
|
|
20
|
+
const raw = Array.isArray(value) ? value.flatMap((entry) => String(entry).split(",")) : String(value).split(",");
|
|
21
|
+
const hostKinds = raw.map((entry) => entry.trim()).filter(Boolean);
|
|
22
|
+
const invalid = hostKinds.find((entry) => !HOST_KINDS.has(entry));
|
|
23
|
+
if (invalid) {
|
|
24
|
+
throw new Error(`Unsupported hosting audit host kind "${invalid}". Expected repository, web, processing, or email.`);
|
|
25
|
+
}
|
|
26
|
+
return [...new Set(hostKinds)];
|
|
27
|
+
}
|
|
28
|
+
function statusCounts(checks) {
|
|
29
|
+
return checks.reduce((counts, check) => {
|
|
30
|
+
counts[check.status] = (counts[check.status] ?? 0) + 1;
|
|
31
|
+
return counts;
|
|
32
|
+
}, {});
|
|
33
|
+
}
|
|
34
|
+
const handleAudit = async (invocation, context) => {
|
|
35
|
+
try {
|
|
36
|
+
const target = invocation.positionals[0] ?? "hosting";
|
|
37
|
+
if (target !== "hosting") {
|
|
38
|
+
throw new Error(`Unsupported audit target "${target}". The available target is "hosting".`);
|
|
39
|
+
}
|
|
40
|
+
const report = await runTreeseedHostingAudit({
|
|
41
|
+
tenantRoot: context.cwd,
|
|
42
|
+
environment: normalizeEnvironment(invocation.args.environment),
|
|
43
|
+
repair: invocation.args.repair === true,
|
|
44
|
+
env: context.env,
|
|
45
|
+
hostKinds: normalizeHostKinds(invocation.args.hostKinds ?? invocation.args.hosts),
|
|
46
|
+
write: context.write
|
|
47
|
+
});
|
|
48
|
+
const counts = statusCounts(report.checks);
|
|
49
|
+
if (context.outputFormat === "json") {
|
|
50
|
+
return {
|
|
51
|
+
exitCode: report.ok ? 0 : 1,
|
|
52
|
+
stdout: [],
|
|
53
|
+
report
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return guidedResult({
|
|
57
|
+
command: "audit",
|
|
58
|
+
summary: formatTreeseedHostingAuditReport(report),
|
|
59
|
+
facts: [
|
|
60
|
+
{ label: "Environment", value: report.environment },
|
|
61
|
+
{ label: "Target", value: report.target.label },
|
|
62
|
+
{ label: "Mode", value: report.repairMode ? "repair" : "read-only" },
|
|
63
|
+
{ label: "Passed", value: counts.passed ?? 0 },
|
|
64
|
+
{ label: "Warnings", value: (counts.warning ?? 0) + report.warnings.length },
|
|
65
|
+
{ label: "Failed", value: counts.failed ?? 0 }
|
|
66
|
+
],
|
|
67
|
+
nextSteps: report.nextActions,
|
|
68
|
+
report,
|
|
69
|
+
exitCode: report.ok ? 0 : 1
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return workflowErrorResult(error);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export {
|
|
76
|
+
handleAudit
|
|
77
|
+
};
|
|
@@ -1260,6 +1260,48 @@ const CLI_COMMAND_OVERLAYS = /* @__PURE__ */ new Map([
|
|
|
1260
1260
|
["starlight:patch", command({ examples: ["treeseed starlight:patch"], executionMode: "adapter" })]
|
|
1261
1261
|
]);
|
|
1262
1262
|
const CLI_ONLY_OPERATION_SPECS = [
|
|
1263
|
+
{
|
|
1264
|
+
id: "audit.hosting",
|
|
1265
|
+
name: "audit",
|
|
1266
|
+
aliases: [],
|
|
1267
|
+
group: "Validation",
|
|
1268
|
+
summary: "Audit TreeSeed hosting readiness.",
|
|
1269
|
+
description: "Run a read-only or explicit repair audit for Repository, Web, Processing, and Email hosting setup.",
|
|
1270
|
+
provider: "default",
|
|
1271
|
+
related: ["status", "config", "save", "release"],
|
|
1272
|
+
usage: "treeseed audit hosting [--environment current|local|staging|prod] [--repair] [--json]",
|
|
1273
|
+
arguments: [{ name: "target", description: "Audit target. Use hosting.", required: false }],
|
|
1274
|
+
options: [
|
|
1275
|
+
{ name: "environment", flags: "--environment <environment>", description: "Audit environment. Defaults to current branch mapping.", kind: "enum", values: ["current", "local", "staging", "prod"] },
|
|
1276
|
+
{ name: "repair", flags: "--repair", description: "Explicitly reconcile missing platform/provider resources.", kind: "boolean" },
|
|
1277
|
+
{ name: "hostKinds", flags: "--host-kinds <kinds>", description: "Comma-separated host kinds to audit.", kind: "string" },
|
|
1278
|
+
{ name: "json", flags: "--json", description: "Emit the hosting audit report as JSON.", kind: "boolean" }
|
|
1279
|
+
],
|
|
1280
|
+
examples: ["treeseed audit hosting", "treeseed audit hosting --environment staging --json", "treeseed audit hosting --repair --environment prod"],
|
|
1281
|
+
help: {
|
|
1282
|
+
workflowPosition: "validate",
|
|
1283
|
+
longSummary: [
|
|
1284
|
+
"The hosting audit proves that TreeSeed can use its configured Repository, Web, Processing, and Email platforms before saving hosts or launching team projects.",
|
|
1285
|
+
"It is read-only by default. Use `--repair` only when you explicitly want TreeSeed to reconcile provider resources."
|
|
1286
|
+
],
|
|
1287
|
+
whenToUse: [
|
|
1288
|
+
"Run this before saving managed hosts, launching a hub, or promoting a release that depends on hosted provider resources.",
|
|
1289
|
+
"Use it after changing provider credentials or service topology to verify that the selected environment is complete."
|
|
1290
|
+
],
|
|
1291
|
+
beforeYouRun: [
|
|
1292
|
+
"Run from the TreeSeed workspace you want to audit.",
|
|
1293
|
+
"Use `--json` for automation and `--repair` only for deliberate provider reconciliation."
|
|
1294
|
+
],
|
|
1295
|
+
automationNotes: [
|
|
1296
|
+
"The report lists missing key names and resource identifiers but never prints decrypted secret values.",
|
|
1297
|
+
"Save, stage, and release resource verification can include the same read-only audit; repair remains explicit."
|
|
1298
|
+
]
|
|
1299
|
+
},
|
|
1300
|
+
helpVisible: true,
|
|
1301
|
+
helpFeatured: true,
|
|
1302
|
+
executionMode: "handler",
|
|
1303
|
+
handlerName: "audit"
|
|
1304
|
+
},
|
|
1263
1305
|
{
|
|
1264
1306
|
id: "tools.gh",
|
|
1265
1307
|
name: "gh",
|
package/dist/cli/registry.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare const COMMAND_HANDLERS: {
|
|
|
38
38
|
readonly 'secrets:migrate-key': import("./operations-types.js").TreeseedCommandHandler;
|
|
39
39
|
readonly 'secrets:rotate-passphrase': import("./operations-types.js").TreeseedCommandHandler;
|
|
40
40
|
readonly 'secrets:rotate-machine-key': import("./operations-types.js").TreeseedCommandHandler;
|
|
41
|
+
readonly audit: import("./operations-types.js").TreeseedCommandHandler;
|
|
41
42
|
};
|
|
42
43
|
export declare const TRESEED_COMMAND_SPECS: TreeseedCommandSpec[];
|
|
43
44
|
export declare function findCommandSpec(name: string | null | undefined): import("./operations-types.js").TreeseedOperationSpec | null;
|
package/dist/cli/registry.js
CHANGED
|
@@ -40,6 +40,7 @@ import { handleExport } from "./handlers/export.js";
|
|
|
40
40
|
import { handleResume } from "./handlers/resume.js";
|
|
41
41
|
import { handleRecover } from "./handlers/recover.js";
|
|
42
42
|
import { handleWorkspace } from "./handlers/workspace.js";
|
|
43
|
+
import { handleAudit } from "./handlers/audit.js";
|
|
43
44
|
const workspaceCommand = (name) => `workspace${":"}${name}`;
|
|
44
45
|
const COMMAND_HANDLERS = {
|
|
45
46
|
init: handleInit,
|
|
@@ -81,7 +82,8 @@ const COMMAND_HANDLERS = {
|
|
|
81
82
|
"secrets:lock": handleSecretsLock,
|
|
82
83
|
"secrets:migrate-key": handleSecretsMigrateKey,
|
|
83
84
|
"secrets:rotate-passphrase": handleSecretsRotatePassphrase,
|
|
84
|
-
"secrets:rotate-machine-key": handleSecretsRotateMachineKey
|
|
85
|
+
"secrets:rotate-machine-key": handleSecretsRotateMachineKey,
|
|
86
|
+
audit: handleAudit
|
|
85
87
|
};
|
|
86
88
|
const TRESEED_COMMAND_SPECS = TRESEED_OPERATION_SPECS;
|
|
87
89
|
function findCommandSpec(name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Operator-facing Treeseed CLI package.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"release:publish": "node ./scripts/run-ts.mjs ./scripts/publish-package.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@treeseed/sdk": "0.8.
|
|
48
|
+
"@treeseed/sdk": "0.8.2",
|
|
49
49
|
"ink": "^7.0.0",
|
|
50
50
|
"react": "^19.2.5"
|
|
51
51
|
},
|