@greenarmor/ges 1.2.0 → 1.2.1

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.
Files changed (2) hide show
  1. package/dist/commands/fix.js +67 -0
  2. package/package.json +14 -14
@@ -2,6 +2,25 @@ import { Command } from "commander";
2
2
  import { ensureGESInitialized } from "../utils/project.js";
3
3
  import { runAudit, deduplicateFindings } from "@greenarmor/ges-audit-engine";
4
4
  import { createAutoFixPlan, applyAutoFixAction, getNpmInstallsFromActions } from "@greenarmor/ges-mcp-server";
5
+ import { appendFixHistory, createFixHistoryEntry } from "@greenarmor/ges-core";
6
+ import { getAllPacks } from "@greenarmor/ges-policy-engine";
7
+ import * as fs from "node:fs";
8
+ import * as path from "node:path";
9
+ function loadProjectControls(root) {
10
+ try {
11
+ const configPath = path.join(root, ".ges", "config.json");
12
+ if (!fs.existsSync(configPath))
13
+ return [];
14
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
15
+ const fwLower = new Set(config.frameworks.map((f) => f.toLowerCase()));
16
+ const allPacks = getAllPacks();
17
+ const filtered = allPacks.filter(pack => fwLower.has(pack.id.toLowerCase()));
18
+ return filtered.flatMap((p) => p.controls);
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ }
5
24
  export const fixCommand = new Command("fix")
6
25
  .description("Automatically fix security and compliance findings")
7
26
  .option("-d, --dry-run", "Show what would be fixed without making changes")
@@ -14,6 +33,7 @@ export const fixCommand = new Command("fix")
14
33
  console.log(" Scanning project files...");
15
34
  const { findings: rawFindings, scannedFiles } = runAudit(root);
16
35
  const findings = deduplicateFindings(rawFindings);
36
+ const projectControls = loadProjectControls(root);
17
37
  console.log(` Scanned ${scannedFiles} files`);
18
38
  console.log(` Found ${findings.length} findings\n`);
19
39
  if (findings.length === 0) {
@@ -45,11 +65,35 @@ export const fixCommand = new Command("fix")
45
65
  }
46
66
  let applied = 0;
47
67
  let failed = 0;
68
+ const historyEntries = [];
48
69
  for (const action of actions) {
70
+ const matchingFindings = findings.filter(f => f.ruleId === action.ruleId);
71
+ const primaryFinding = matchingFindings[0];
72
+ const matchedControls = primaryFinding
73
+ ? projectControls.filter((c) => primaryFinding.controlIds.includes(c.id))
74
+ : [];
49
75
  if (dryRun) {
50
76
  console.log(` [${action.type}] ${action.filePath}`);
51
77
  console.log(` ${action.description} [${action.ruleId}]`);
52
78
  applied++;
79
+ historyEntries.push(createFixHistoryEntry({
80
+ source: "cli",
81
+ dry_run: true,
82
+ finding: primaryFinding ?? {
83
+ ruleId: action.ruleId,
84
+ severity: "medium",
85
+ category: "",
86
+ title: action.description,
87
+ file: "",
88
+ evidence: "",
89
+ description: action.description,
90
+ controlIds: [],
91
+ fix: action.description,
92
+ },
93
+ action,
94
+ controls: matchedControls,
95
+ applied: false,
96
+ }));
53
97
  }
54
98
  else {
55
99
  const result = applyAutoFixAction(root, action);
@@ -62,8 +106,31 @@ export const fixCommand = new Command("fix")
62
106
  console.log(` ${result.error}`);
63
107
  failed++;
64
108
  }
109
+ historyEntries.push(createFixHistoryEntry({
110
+ source: "cli",
111
+ dry_run: false,
112
+ finding: primaryFinding ?? {
113
+ ruleId: action.ruleId,
114
+ severity: "medium",
115
+ category: "",
116
+ title: action.description,
117
+ file: "",
118
+ evidence: "",
119
+ description: action.description,
120
+ controlIds: [],
121
+ fix: action.description,
122
+ },
123
+ action,
124
+ controls: matchedControls,
125
+ applied: result.applied,
126
+ error: result.applied ? undefined : result.error,
127
+ }));
65
128
  }
66
129
  }
130
+ if (historyEntries.length > 0 && !dryRun) {
131
+ appendFixHistory(root, historyEntries);
132
+ console.log(`\n Fix history recorded in .ges/fix-history.json`);
133
+ }
67
134
  console.log("");
68
135
  console.log(` Fixes ${dryRun ? "planned" : "applied"}: ${applied}${failed > 0 ? ` (${failed} failed)` : ""}`);
69
136
  if (npmInstalls.length > 0) {
package/package.json CHANGED
@@ -3,19 +3,19 @@
3
3
  "ges": "./dist/cli.js"
4
4
  },
5
5
  "dependencies": {
6
- "@greenarmor/ges-audit-engine": "1.2.0",
7
- "@greenarmor/ges-cicd-generator": "1.2.0",
8
- "@greenarmor/ges-compliance-engine": "1.2.0",
9
- "@greenarmor/ges-core": "1.2.0",
10
- "@greenarmor/ges-doc-generator": "1.2.0",
11
- "@greenarmor/ges-git-hooks": "1.2.0",
12
- "@greenarmor/ges-mcp-server": "1.2.0",
13
- "@greenarmor/ges-policy-engine": "1.2.0",
14
- "@greenarmor/ges-report-generator": "1.2.0",
15
- "@greenarmor/ges-rules-engine": "1.2.0",
16
- "@greenarmor/ges-scanner-integration": "1.2.0",
17
- "@greenarmor/ges-scoring-engine": "1.2.0",
18
- "@greenarmor/ges-web-dashboard": "1.2.0",
6
+ "@greenarmor/ges-audit-engine": "1.2.1",
7
+ "@greenarmor/ges-cicd-generator": "1.2.1",
8
+ "@greenarmor/ges-compliance-engine": "1.2.1",
9
+ "@greenarmor/ges-core": "1.2.1",
10
+ "@greenarmor/ges-doc-generator": "1.2.1",
11
+ "@greenarmor/ges-git-hooks": "1.2.1",
12
+ "@greenarmor/ges-mcp-server": "1.2.1",
13
+ "@greenarmor/ges-policy-engine": "1.2.1",
14
+ "@greenarmor/ges-report-generator": "1.2.1",
15
+ "@greenarmor/ges-rules-engine": "1.2.1",
16
+ "@greenarmor/ges-scanner-integration": "1.2.1",
17
+ "@greenarmor/ges-scoring-engine": "1.2.1",
18
+ "@greenarmor/ges-web-dashboard": "1.2.1",
19
19
  "commander": "^13.0.0"
20
20
  },
21
21
  "description": "Green Engineering Standard Framework - Compliance-as-Code CLI",
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "type": "module",
55
55
  "types": "./dist/index.d.ts",
56
- "version": "1.2.0",
56
+ "version": "1.2.1",
57
57
  "scripts": {
58
58
  "build": "tsc",
59
59
  "clean": "rm -rf dist tsconfig.tsbuildinfo",