@clawops/cli 1.6.0 → 1.7.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/README.md +1 -0
- package/dist/{apply-SI3JKS4Z.js → apply-BTZFFGAD.js} +2 -2
- package/dist/{chunk-72FF7IK2.js → chunk-7KLLWDBA.js} +2 -2
- package/dist/{chunk-C5NDLOK2.js → chunk-CG3Y7Y2R.js} +39 -70
- package/dist/{chunk-QHGFENYR.js → chunk-ISFHLA4G.js} +3 -3
- package/dist/chunk-Q7NQY5HV.js +37 -0
- package/dist/cli.js +273 -37
- package/dist/{context-KPKBOWOP.js → context-ALSJMTHE.js} +1 -1
- package/dist/{generate-YV7226Q7.js → generate-ZTD4BVVI.js} +2 -2
- package/dist/harden-BDVYW567.js +748 -0
- package/dist/human-Z44CW7TR.js +21 -0
- package/dist/{package-EW3FS257.js → package-7WOZMHSO.js} +5 -1
- package/dist/{server-3DEZHUWB.js → server-EXBOOIEP.js} +7 -6
- package/package.json +5 -1
- /package/dist/{chunk-QI75OVJK.js → chunk-3MFZ7E74.js} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
monitor_default,
|
|
4
|
+
validateOpenclawConfig
|
|
5
|
+
} from "./chunk-CG3Y7Y2R.js";
|
|
2
6
|
import {
|
|
3
7
|
MCP_APPS,
|
|
4
8
|
buildMcpEntry,
|
|
5
9
|
writeAppConfigs
|
|
6
10
|
} from "./chunk-OIGTOLB3.js";
|
|
11
|
+
import "./chunk-ZFNPM2WG.js";
|
|
12
|
+
import "./chunk-3MFZ7E74.js";
|
|
13
|
+
import "./chunk-LCKD7L7X.js";
|
|
14
|
+
import "./chunk-GJEF6UQA.js";
|
|
7
15
|
import {
|
|
8
16
|
REPO_URL,
|
|
9
17
|
chalk,
|
|
10
18
|
failure,
|
|
11
19
|
info,
|
|
12
|
-
monitor_default,
|
|
13
20
|
printCta,
|
|
14
21
|
spinner,
|
|
15
22
|
success,
|
|
16
|
-
validateOpenclawConfig,
|
|
17
23
|
warn
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-QI75OVJK.js";
|
|
20
|
-
import "./chunk-LCKD7L7X.js";
|
|
21
|
-
import "./chunk-GJEF6UQA.js";
|
|
22
|
-
import "./chunk-ZFNPM2WG.js";
|
|
24
|
+
} from "./chunk-Q7NQY5HV.js";
|
|
23
25
|
import "./chunk-A2I76FTA.js";
|
|
24
26
|
import {
|
|
25
27
|
getConfig,
|
|
@@ -33,7 +35,7 @@ import {
|
|
|
33
35
|
} from "./chunk-KGXPLI7W.js";
|
|
34
36
|
|
|
35
37
|
// src/cli/index.ts
|
|
36
|
-
import { defineCommand as
|
|
38
|
+
import { defineCommand as defineCommand23, runMain } from "citty";
|
|
37
39
|
|
|
38
40
|
// src/cli/commands/init.ts
|
|
39
41
|
import { defineCommand } from "citty";
|
|
@@ -205,7 +207,7 @@ var up_default = defineCommand2({
|
|
|
205
207
|
config: { type: "string", description: "Path to openclaw config overlay JSON (local provider only)" }
|
|
206
208
|
},
|
|
207
209
|
async run({ args }) {
|
|
208
|
-
const { buildContext } = await import("./context-
|
|
210
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
209
211
|
const ctx = buildContext(args);
|
|
210
212
|
const openclawVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : "stable";
|
|
211
213
|
if (ctx.adapter.name === "local") {
|
|
@@ -351,7 +353,7 @@ var down_default = defineCommand3({
|
|
|
351
353
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
352
354
|
},
|
|
353
355
|
async run({ args }) {
|
|
354
|
-
const { buildContext } = await import("./context-
|
|
356
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
355
357
|
const ctx = buildContext(args);
|
|
356
358
|
if (args["dry-run"]) {
|
|
357
359
|
info(`Dry run \u2014 would destroy stack "${ctx.stackName}"`);
|
|
@@ -415,7 +417,7 @@ var status_default = defineCommand4({
|
|
|
415
417
|
json: { type: "boolean", description: "Emit JSON" }
|
|
416
418
|
},
|
|
417
419
|
async run({ args }) {
|
|
418
|
-
const { buildContext } = await import("./context-
|
|
420
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
419
421
|
const ctx = buildContext(args);
|
|
420
422
|
if (ctx.adapter.name === "local") {
|
|
421
423
|
const state = ctx.localState;
|
|
@@ -487,8 +489,8 @@ var plan_default = defineCommand5({
|
|
|
487
489
|
out: { type: "string", description: "Write plan JSON to this absolute path (default: stdout)" }
|
|
488
490
|
},
|
|
489
491
|
async run({ args }) {
|
|
490
|
-
const { buildContext } = await import("./context-
|
|
491
|
-
const { generatePlan } = await import("./generate-
|
|
492
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
493
|
+
const { generatePlan } = await import("./generate-ZTD4BVVI.js");
|
|
492
494
|
const ctx = buildContext(args);
|
|
493
495
|
if (ctx.adapter.name === "local") {
|
|
494
496
|
throw new UsageError(
|
|
@@ -578,7 +580,7 @@ var apply_default = defineCommand6({
|
|
|
578
580
|
},
|
|
579
581
|
async run({ args }) {
|
|
580
582
|
const { validatePlan } = await import("./validate-T5M5EHSJ.js");
|
|
581
|
-
const { applyPlan } = await import("./apply-
|
|
583
|
+
const { applyPlan } = await import("./apply-BTZFFGAD.js");
|
|
582
584
|
const planPath = args._?.[0];
|
|
583
585
|
if (!planPath) {
|
|
584
586
|
throw new UsageError("Usage: clawops apply <plan.json>");
|
|
@@ -694,7 +696,7 @@ var destroy_default = defineCommand7({
|
|
|
694
696
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
695
697
|
},
|
|
696
698
|
async run({ args }) {
|
|
697
|
-
const { buildContext } = await import("./context-
|
|
699
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
698
700
|
const ctx = buildContext(args);
|
|
699
701
|
if (ctx.adapter.name === "local") {
|
|
700
702
|
throw new UsageError(
|
|
@@ -761,7 +763,7 @@ var ssh_default = defineCommand8({
|
|
|
761
763
|
command: { type: "string", description: "Remote command to run (instead of interactive shell)" }
|
|
762
764
|
},
|
|
763
765
|
async run({ args }) {
|
|
764
|
-
const { buildContext } = await import("./context-
|
|
766
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
765
767
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
766
768
|
const ctx = buildContext(args);
|
|
767
769
|
let conn;
|
|
@@ -848,7 +850,7 @@ var tunnel_default = defineCommand9({
|
|
|
848
850
|
"no-open": { type: "boolean", description: "Do not open browser after tunnel is ready" }
|
|
849
851
|
},
|
|
850
852
|
async run({ args }) {
|
|
851
|
-
const { buildContext } = await import("./context-
|
|
853
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
852
854
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
853
855
|
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
854
856
|
const ctx = buildContext(args);
|
|
@@ -916,7 +918,7 @@ var logs_default = defineCommand10({
|
|
|
916
918
|
since: { type: "string", description: "Show logs since duration (e.g. 5m, 1h)" }
|
|
917
919
|
},
|
|
918
920
|
async run({ args }) {
|
|
919
|
-
const { buildContext } = await import("./context-
|
|
921
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
920
922
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
921
923
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
922
924
|
const ctx = buildContext(args);
|
|
@@ -1033,7 +1035,7 @@ var config_default = defineCommand11({
|
|
|
1033
1035
|
"dry-run": { type: "boolean", description: "Show what would change without writing" }
|
|
1034
1036
|
},
|
|
1035
1037
|
async run({ args }) {
|
|
1036
|
-
const { buildContext } = await import("./context-
|
|
1038
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1037
1039
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1038
1040
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1039
1041
|
const [action, key, value] = args._ ?? [];
|
|
@@ -1159,7 +1161,7 @@ var agents_default = defineCommand12({
|
|
|
1159
1161
|
json: { type: "boolean", description: "Emit JSON (for list)" }
|
|
1160
1162
|
},
|
|
1161
1163
|
async run({ args }) {
|
|
1162
|
-
const { buildContext } = await import("./context-
|
|
1164
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1163
1165
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1164
1166
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1165
1167
|
const [action, name] = args._ ?? [];
|
|
@@ -1263,7 +1265,7 @@ var gateway_default = defineCommand13({
|
|
|
1263
1265
|
json: { type: "boolean", description: "Emit JSON (for status)" }
|
|
1264
1266
|
},
|
|
1265
1267
|
async run({ args }) {
|
|
1266
|
-
const { buildContext } = await import("./context-
|
|
1268
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1267
1269
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1268
1270
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1269
1271
|
const [action, versionArg] = args._ ?? [];
|
|
@@ -1376,7 +1378,7 @@ var backup_default = defineCommand14({
|
|
|
1376
1378
|
yes: { type: "boolean", description: "[restore] Skip confirmation prompt" }
|
|
1377
1379
|
},
|
|
1378
1380
|
async run({ args }) {
|
|
1379
|
-
const { buildContext } = await import("./context-
|
|
1381
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1380
1382
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1381
1383
|
const action = args.action;
|
|
1382
1384
|
if (action !== "create" && action !== "restore") {
|
|
@@ -1549,7 +1551,7 @@ var stacks_default = defineCommand15({
|
|
|
1549
1551
|
let isDeployed = false;
|
|
1550
1552
|
if (!args.force) {
|
|
1551
1553
|
try {
|
|
1552
|
-
const { buildContext } = await import("./context-
|
|
1554
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1553
1555
|
const ctx = buildContext({ stack: name });
|
|
1554
1556
|
if (ctx.adapter.name === "local") {
|
|
1555
1557
|
isDeployed = !!ctx.localState;
|
|
@@ -1707,7 +1709,7 @@ var doctor_default = defineCommand16({
|
|
|
1707
1709
|
info("Remote health skipped \u2014 no config");
|
|
1708
1710
|
} else {
|
|
1709
1711
|
try {
|
|
1710
|
-
const { buildContext } = await import("./context-
|
|
1712
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1711
1713
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1712
1714
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1713
1715
|
const ctx = buildContext({ stack: args.stack });
|
|
@@ -1793,6 +1795,44 @@ var doctor_default = defineCommand16({
|
|
|
1793
1795
|
}
|
|
1794
1796
|
}
|
|
1795
1797
|
}
|
|
1798
|
+
if (args.stack && config) {
|
|
1799
|
+
process18.stdout.write("\nHardening\n");
|
|
1800
|
+
try {
|
|
1801
|
+
const { MODULE_CATALOG, resolveModules, withRemoteExec } = await import("./harden-BDVYW567.js");
|
|
1802
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1803
|
+
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1804
|
+
const ctx = buildContext({ stack: args.stack });
|
|
1805
|
+
const stackObj = await ctx.getStack();
|
|
1806
|
+
const outputMap = await stackObj.outputs();
|
|
1807
|
+
const outputs = Object.fromEntries(
|
|
1808
|
+
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
1809
|
+
);
|
|
1810
|
+
const base = extractBaseOutputs(outputs);
|
|
1811
|
+
const conn = ctx.adapter.getConnectionInfo({
|
|
1812
|
+
...base,
|
|
1813
|
+
privateKeyPath: config.ssh.keyPath,
|
|
1814
|
+
knownHostsPath: config.ssh.knownHostsPath
|
|
1815
|
+
});
|
|
1816
|
+
const hardenAc = new AbortController();
|
|
1817
|
+
process18.on("SIGINT", () => hardenAc.abort());
|
|
1818
|
+
const provider = ctx.adapter.name;
|
|
1819
|
+
const modules = resolveModules(MODULE_CATALOG, void 0, provider);
|
|
1820
|
+
await withRemoteExec(conn, hardenAc.signal, async (exec) => {
|
|
1821
|
+
for (const mod of modules) {
|
|
1822
|
+
const result = await mod.check(exec);
|
|
1823
|
+
if (result.status === "applied") {
|
|
1824
|
+
success(`${mod.label.padEnd(32)} applied`);
|
|
1825
|
+
} else if (result.status === "drifted") {
|
|
1826
|
+
warn(`${mod.label.padEnd(32)} drifted \u2014 ${result.detail}`);
|
|
1827
|
+
} else if (result.status === "missing") {
|
|
1828
|
+
info(`${mod.label.padEnd(32)} not applied \u2014 run \`clawops harden\``);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
});
|
|
1832
|
+
} catch (err) {
|
|
1833
|
+
failure(`Hardening checks failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1796
1836
|
process18.stdout.write("\n");
|
|
1797
1837
|
if (!nodeOk) {
|
|
1798
1838
|
process18.stdout.write(
|
|
@@ -1822,7 +1862,7 @@ var serveCmd = defineCommand17({
|
|
|
1822
1862
|
inspector: { type: "boolean", description: "Enable MCP inspector" }
|
|
1823
1863
|
},
|
|
1824
1864
|
async run({ args }) {
|
|
1825
|
-
const { serveMcp } = await import("./server-
|
|
1865
|
+
const { serveMcp } = await import("./server-EXBOOIEP.js");
|
|
1826
1866
|
await serveMcp({
|
|
1827
1867
|
port: args.http ? Number(args.http) : void 0,
|
|
1828
1868
|
bind: args.bind,
|
|
@@ -1897,7 +1937,7 @@ var wireCmd = defineCommand17({
|
|
|
1897
1937
|
force: { type: "boolean", description: "Apply even if gateway version is below minimum" }
|
|
1898
1938
|
},
|
|
1899
1939
|
async run({ args }) {
|
|
1900
|
-
const { buildContext } = await import("./context-
|
|
1940
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
1901
1941
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1902
1942
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1903
1943
|
const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
|
|
@@ -2394,6 +2434,12 @@ var setup_default = defineCommand18({
|
|
|
2394
2434
|
signal: ac.signal,
|
|
2395
2435
|
inquirer
|
|
2396
2436
|
});
|
|
2437
|
+
await maybeHarden({
|
|
2438
|
+
stackName: stackAnswers.stackName,
|
|
2439
|
+
provider: "local",
|
|
2440
|
+
signal: ac.signal,
|
|
2441
|
+
inquirer
|
|
2442
|
+
});
|
|
2397
2443
|
} else {
|
|
2398
2444
|
const { getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2399
2445
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
@@ -2412,7 +2458,7 @@ var setup_default = defineCommand18({
|
|
|
2412
2458
|
default: false
|
|
2413
2459
|
}]);
|
|
2414
2460
|
if (applyNow) {
|
|
2415
|
-
const { applyPlan } = await import("./apply-
|
|
2461
|
+
const { applyPlan } = await import("./apply-BTZFFGAD.js");
|
|
2416
2462
|
const plan = JSON.parse(readFileSync3(outputPath, "utf-8"));
|
|
2417
2463
|
try {
|
|
2418
2464
|
await applyPlan(plan, {
|
|
@@ -2426,6 +2472,12 @@ var setup_default = defineCommand18({
|
|
|
2426
2472
|
process20.exit(1);
|
|
2427
2473
|
}
|
|
2428
2474
|
await maybeWireGatewayMcpCloud({ stackName: stackAnswers.stackName, signal: ac.signal, inquirer });
|
|
2475
|
+
await maybeHarden({
|
|
2476
|
+
stackName: stackAnswers.stackName,
|
|
2477
|
+
provider,
|
|
2478
|
+
signal: ac.signal,
|
|
2479
|
+
inquirer
|
|
2480
|
+
});
|
|
2429
2481
|
} else {
|
|
2430
2482
|
info(`
|
|
2431
2483
|
To deploy later: clawops apply ${outputPath}`);
|
|
@@ -3000,6 +3052,68 @@ function instanceChoices(provider) {
|
|
|
3000
3052
|
};
|
|
3001
3053
|
return table[provider] ?? [];
|
|
3002
3054
|
}
|
|
3055
|
+
async function maybeHarden(opts) {
|
|
3056
|
+
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-BDVYW567.js");
|
|
3057
|
+
const { getConfig: getConfig2 } = await import("./store-SDUR52Z5.js");
|
|
3058
|
+
const config = getConfig2();
|
|
3059
|
+
if (!config) return;
|
|
3060
|
+
const availableModules = resolveModules(MODULE_CATALOG, void 0, opts.provider);
|
|
3061
|
+
if (availableModules.length === 0) return;
|
|
3062
|
+
process20.stdout.write("\n");
|
|
3063
|
+
const { selectedIds } = await opts.inquirer.prompt([{
|
|
3064
|
+
type: "checkbox",
|
|
3065
|
+
name: "selectedIds",
|
|
3066
|
+
message: "Apply security hardening? (Space to toggle, Enter to confirm)",
|
|
3067
|
+
choices: availableModules.map((m) => ({
|
|
3068
|
+
name: `${m.label}${m.defaultOn ? "" : " (opt-in)"}`,
|
|
3069
|
+
value: m.id,
|
|
3070
|
+
checked: m.defaultOn
|
|
3071
|
+
}))
|
|
3072
|
+
}]);
|
|
3073
|
+
if (selectedIds.length === 0) {
|
|
3074
|
+
info("Hardening skipped. Run `clawops harden --stack " + opts.stackName + "` later.");
|
|
3075
|
+
return;
|
|
3076
|
+
}
|
|
3077
|
+
const modules = availableModules.filter((m) => selectedIds.includes(m.id));
|
|
3078
|
+
process20.stdout.write("\nApplying hardening modules...\n\n");
|
|
3079
|
+
try {
|
|
3080
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
3081
|
+
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
3082
|
+
const ctx = buildContext({ stack: opts.stackName });
|
|
3083
|
+
const stackObj = await ctx.getStack();
|
|
3084
|
+
const outputMap = await stackObj.outputs();
|
|
3085
|
+
const outputs = Object.fromEntries(
|
|
3086
|
+
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
3087
|
+
);
|
|
3088
|
+
const base = extractBaseOutputs(outputs);
|
|
3089
|
+
const conn = ctx.adapter.getConnectionInfo({
|
|
3090
|
+
...base,
|
|
3091
|
+
privateKeyPath: config.ssh.keyPath,
|
|
3092
|
+
knownHostsPath: config.ssh.knownHostsPath
|
|
3093
|
+
});
|
|
3094
|
+
const { success: ok, failure: fail } = await import("./human-Z44CW7TR.js");
|
|
3095
|
+
const results = await runHardening(conn, {
|
|
3096
|
+
modules,
|
|
3097
|
+
signal: opts.signal,
|
|
3098
|
+
onProgress: (r) => {
|
|
3099
|
+
process20.stdout.write(` \xB7 ${r.module.label}
|
|
3100
|
+
`);
|
|
3101
|
+
}
|
|
3102
|
+
});
|
|
3103
|
+
process20.stdout.write("\n" + formatHardenSummary(results));
|
|
3104
|
+
const errors = results.filter((r) => r.error);
|
|
3105
|
+
if (errors.length > 0) {
|
|
3106
|
+
for (const r of errors) fail(`${r.module.label}: ${r.error}`);
|
|
3107
|
+
info("Some modules failed. Run `clawops harden --stack " + opts.stackName + "` to retry.");
|
|
3108
|
+
} else {
|
|
3109
|
+
ok("Hardening complete.");
|
|
3110
|
+
}
|
|
3111
|
+
} catch (err) {
|
|
3112
|
+
const { failure: fail } = await import("./human-Z44CW7TR.js");
|
|
3113
|
+
fail(`Hardening failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3114
|
+
info("Run `clawops harden --stack " + opts.stackName + "` to retry.");
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3003
3117
|
|
|
3004
3118
|
// src/cli/commands/secret.ts
|
|
3005
3119
|
import { defineCommand as defineCommand19 } from "citty";
|
|
@@ -3172,7 +3286,7 @@ var rotateCmd = defineCommand19({
|
|
|
3172
3286
|
}
|
|
3173
3287
|
info(`Re-applying config overlay to stack "${targetStack}"\u2026`);
|
|
3174
3288
|
try {
|
|
3175
|
-
const { buildContext } = await import("./context-
|
|
3289
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
3176
3290
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
3177
3291
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
3178
3292
|
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
@@ -3359,7 +3473,7 @@ import { accessSync as accessSync2, constants as constants2 } from "fs";
|
|
|
3359
3473
|
import { execSync as execSync2 } from "child_process";
|
|
3360
3474
|
var ISSUES_URL = `${REPO_URL}/issues/new`;
|
|
3361
3475
|
var BODY_CAP = 2e3;
|
|
3362
|
-
var VERSION = true ? "1.
|
|
3476
|
+
var VERSION = true ? "1.7.0" : "dev";
|
|
3363
3477
|
async function collectContext() {
|
|
3364
3478
|
const nodeVersion = process22.version;
|
|
3365
3479
|
const os3 = `${process22.platform} ${process22.arch}`;
|
|
@@ -3459,26 +3573,147 @@ ${url}
|
|
|
3459
3573
|
}
|
|
3460
3574
|
});
|
|
3461
3575
|
|
|
3462
|
-
// src/cli/
|
|
3576
|
+
// src/cli/commands/harden.ts
|
|
3577
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
3463
3578
|
import process23 from "process";
|
|
3579
|
+
var harden_default = defineCommand22({
|
|
3580
|
+
meta: {
|
|
3581
|
+
name: "harden",
|
|
3582
|
+
description: "Apply security hardening modules to a deployed stack"
|
|
3583
|
+
},
|
|
3584
|
+
args: {
|
|
3585
|
+
stack: { type: "string", description: "Target stack name" },
|
|
3586
|
+
options: { type: "string", description: "Comma-separated module IDs to run (default: all defaultOn modules)" },
|
|
3587
|
+
list: { type: "boolean", description: "List available modules and exit" },
|
|
3588
|
+
"dry-run": { type: "boolean", description: "Check current state without applying changes" },
|
|
3589
|
+
yes: { type: "boolean", description: "Skip confirmation prompt" },
|
|
3590
|
+
json: { type: "boolean", description: "Emit structured JSON output" }
|
|
3591
|
+
},
|
|
3592
|
+
async run({ args }) {
|
|
3593
|
+
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary } = await import("./harden-BDVYW567.js");
|
|
3594
|
+
const { buildContext } = await import("./context-ALSJMTHE.js");
|
|
3595
|
+
const { getConfig: getConfig2 } = await import("./store-SDUR52Z5.js");
|
|
3596
|
+
if (args.list) {
|
|
3597
|
+
process23.stdout.write("\nAvailable hardening modules:\n\n");
|
|
3598
|
+
for (const mod of MODULE_CATALOG) {
|
|
3599
|
+
const on = mod.defaultOn ? chalk.green("ON ") : chalk.dim("off");
|
|
3600
|
+
const providers = mod.providers === "all" ? "all" : mod.providers.join(", ");
|
|
3601
|
+
process23.stdout.write(
|
|
3602
|
+
` ${on} ${mod.id.padEnd(28)} ${mod.label} [${providers}]
|
|
3603
|
+
`
|
|
3604
|
+
);
|
|
3605
|
+
}
|
|
3606
|
+
process23.stdout.write("\n");
|
|
3607
|
+
return;
|
|
3608
|
+
}
|
|
3609
|
+
const config = getConfig2();
|
|
3610
|
+
if (!config) {
|
|
3611
|
+
failure("No clawops config found. Run `clawops init` first.");
|
|
3612
|
+
process23.exit(1);
|
|
3613
|
+
}
|
|
3614
|
+
const ctx = buildContext({ stack: args.stack });
|
|
3615
|
+
const provider = ctx.adapter.name;
|
|
3616
|
+
const modules = resolveModules(MODULE_CATALOG, args.options, provider);
|
|
3617
|
+
if (modules.length === 0) {
|
|
3618
|
+
warn("No modules selected for this provider. Use --options to specify modules or --list to see all.");
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
3621
|
+
if (!args.json) {
|
|
3622
|
+
process23.stdout.write("\nModules to run:\n");
|
|
3623
|
+
for (const mod of modules) {
|
|
3624
|
+
const flag = mod.defaultOn ? "" : chalk.yellow(" [opt-in]");
|
|
3625
|
+
process23.stdout.write(` \xB7 ${mod.label}${flag}
|
|
3626
|
+
`);
|
|
3627
|
+
}
|
|
3628
|
+
process23.stdout.write("\n");
|
|
3629
|
+
}
|
|
3630
|
+
if (!args["dry-run"] && !args.yes && !args.json) {
|
|
3631
|
+
const { createInterface: createInterface3 } = await import("readline/promises");
|
|
3632
|
+
const rl = createInterface3({ input: process23.stdin, output: process23.stdout });
|
|
3633
|
+
const answer = await rl.question("Apply these hardening modules? [y/N] ");
|
|
3634
|
+
rl.close();
|
|
3635
|
+
if (!answer.toLowerCase().startsWith("y")) {
|
|
3636
|
+
info("Aborted.");
|
|
3637
|
+
return;
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
const ac = new AbortController();
|
|
3641
|
+
process23.on("SIGINT", () => ac.abort());
|
|
3642
|
+
process23.on("SIGTERM", () => ac.abort());
|
|
3643
|
+
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
3644
|
+
const stackObj = await ctx.getStack();
|
|
3645
|
+
const outputMap = await stackObj.outputs();
|
|
3646
|
+
const outputs = Object.fromEntries(
|
|
3647
|
+
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
3648
|
+
);
|
|
3649
|
+
const base = extractBaseOutputs(outputs);
|
|
3650
|
+
const conn = ctx.adapter.getConnectionInfo({
|
|
3651
|
+
...base,
|
|
3652
|
+
privateKeyPath: config.ssh.keyPath,
|
|
3653
|
+
knownHostsPath: config.ssh.knownHostsPath
|
|
3654
|
+
});
|
|
3655
|
+
if (!args.json) {
|
|
3656
|
+
process23.stdout.write(args["dry-run"] ? "Checking hardening state...\n\n" : "Applying hardening...\n\n");
|
|
3657
|
+
}
|
|
3658
|
+
const results = await runHardening(conn, {
|
|
3659
|
+
modules,
|
|
3660
|
+
dryRun: args["dry-run"],
|
|
3661
|
+
signal: ac.signal,
|
|
3662
|
+
onProgress: args.json ? void 0 : (r) => {
|
|
3663
|
+
const icon = r.error ? chalk.red("\u2717") : r.applyResult?.changed ? chalk.green("\u2713") : chalk.dim("\xB7");
|
|
3664
|
+
process23.stdout.write(` ${icon} ${r.module.label}
|
|
3665
|
+
`);
|
|
3666
|
+
}
|
|
3667
|
+
});
|
|
3668
|
+
if (args.json) {
|
|
3669
|
+
printJson(jsonOk({
|
|
3670
|
+
dryRun: args["dry-run"] ?? false,
|
|
3671
|
+
results: results.map((r) => ({
|
|
3672
|
+
id: r.module.id,
|
|
3673
|
+
status: r.checkResult.status,
|
|
3674
|
+
changed: r.applyResult?.changed ?? false,
|
|
3675
|
+
detail: r.applyResult?.detail ?? r.checkResult.detail,
|
|
3676
|
+
error: r.error,
|
|
3677
|
+
durationMs: r.durationMs
|
|
3678
|
+
}))
|
|
3679
|
+
}));
|
|
3680
|
+
return;
|
|
3681
|
+
}
|
|
3682
|
+
process23.stdout.write("\n" + formatHardenSummary(results));
|
|
3683
|
+
const errors = results.filter((r) => r.error);
|
|
3684
|
+
if (errors.length > 0) {
|
|
3685
|
+
process23.stdout.write("\n");
|
|
3686
|
+
for (const r of errors) {
|
|
3687
|
+
failure(`${r.module.label}: ${r.error}`);
|
|
3688
|
+
}
|
|
3689
|
+
process23.exit(1);
|
|
3690
|
+
}
|
|
3691
|
+
if (!args["dry-run"]) {
|
|
3692
|
+
success("Hardening complete.");
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
});
|
|
3696
|
+
|
|
3697
|
+
// src/cli/error-handler.ts
|
|
3698
|
+
import process24 from "process";
|
|
3464
3699
|
function handleError(err) {
|
|
3465
3700
|
if (err instanceof ClawopsError) {
|
|
3466
3701
|
failure(err.message);
|
|
3467
|
-
|
|
3702
|
+
process24.exit(err.exitCode);
|
|
3468
3703
|
}
|
|
3469
3704
|
if (err instanceof Error) {
|
|
3470
3705
|
failure(`Unexpected error: ${err.message}`);
|
|
3471
|
-
if (
|
|
3472
|
-
|
|
3706
|
+
if (process24.env["DEBUG"]) {
|
|
3707
|
+
process24.stderr.write(err.stack ?? "\n");
|
|
3473
3708
|
}
|
|
3474
|
-
|
|
3709
|
+
process24.exit(1);
|
|
3475
3710
|
}
|
|
3476
3711
|
failure(`Unknown error: ${String(err)}`);
|
|
3477
|
-
|
|
3712
|
+
process24.exit(1);
|
|
3478
3713
|
}
|
|
3479
3714
|
|
|
3480
3715
|
// src/cli/index.ts
|
|
3481
|
-
var main =
|
|
3716
|
+
var main = defineCommand23({
|
|
3482
3717
|
meta: {
|
|
3483
3718
|
name: "clawops",
|
|
3484
3719
|
description: "Deploy and manage self-hosted OpenClaw instances across clouds",
|
|
@@ -3515,7 +3750,8 @@ var main = defineCommand22({
|
|
|
3515
3750
|
secret: secret_default,
|
|
3516
3751
|
monitor: monitor_default,
|
|
3517
3752
|
help: help_default,
|
|
3518
|
-
bug: bug_default
|
|
3753
|
+
bug: bug_default,
|
|
3754
|
+
harden: harden_default
|
|
3519
3755
|
}
|
|
3520
3756
|
});
|
|
3521
3757
|
try {
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
generatePlan,
|
|
4
4
|
planId
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7KLLWDBA.js";
|
|
6
6
|
import "./chunk-YTH4L2GN.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-3MFZ7E74.js";
|
|
8
8
|
import "./chunk-A2I76FTA.js";
|
|
9
9
|
import "./chunk-CX5SL5HP.js";
|
|
10
10
|
import "./chunk-KGXPLI7W.js";
|