@greenarmor/ges 1.5.3 → 1.5.4

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.
@@ -1,7 +1,7 @@
1
1
  import { Command } from "commander";
2
2
  import { ensureGESInitialized } from "../utils/project.js";
3
3
  import { input, select } from "../utils/prompts.js";
4
- import { banner, divider, blank, success, error, warn, info, kv, statusBadge, severityBadge, BOLD, DIM, GREEN, RED, YELLOW, GRAY, } from "../utils/ui.js";
4
+ import { banner, divider, blank, success, error, warn, info, kv, label, statusBadge, severityBadge, BOLD, DIM, GREEN, RED, YELLOW, GRAY, } from "../utils/ui.js";
5
5
  import { loadGovernanceRecords, createGovernanceRecord, addGovernanceRecord, findGovernanceRecord, setGovernanceApproval, addGovernanceEvidence, createEvidenceRef, verifyGovernanceRecord, deleteGovernanceRecord, setGovernanceRiskAssessment, setGovernancePolicyBasis, setGovernanceReviewCycle, setGovernanceDataInventory, setGovernanceComplianceLinks, setGovernanceCommittee, } from "@greenarmor/ges-core";
6
6
  import { recordActivity } from "@greenarmor/ges-core";
7
7
  const STATUS_BADGE = {
@@ -32,6 +32,70 @@ function printRecordSummary(record) {
32
32
  }
33
33
  console.log(` ${DIM("Ev")} ${record.evidence.length} reference(s)`);
34
34
  }
35
+ async function showGovernanceNextAction(root, records, lastShownId) {
36
+ if (process.stdin.isTTY !== true || process.stdout.isTTY !== true)
37
+ return;
38
+ const choices = [];
39
+ if (lastShownId) {
40
+ choices.push({ name: `Verify this record ${DIM("— check provenance completeness")}`, value: `ges governance verify ${lastShownId}` });
41
+ if (records.length > 1) {
42
+ choices.push({ name: `Show another record ${DIM("— pick from list")}`, value: `__pick_show__` });
43
+ }
44
+ choices.push({ name: `Record an approval ${DIM("— add approval decision")}`, value: `ges governance approve ${lastShownId}` });
45
+ choices.push({ name: `Add evidence reference ${DIM("— link to Jira/Confluence/etc")}`, value: `ges governance evidence ${lastShownId}` });
46
+ choices.push({ name: `Link risk assessment ${DIM("— assessor, methodology, score")}`, value: `ges governance risk-assessment ${lastShownId}` });
47
+ choices.push({ name: `Document policy basis ${DIM("— which policy applies")}`, value: `ges governance policy-basis ${lastShownId}` });
48
+ }
49
+ else if (records.length > 0) {
50
+ choices.push({ name: `Show a record's full provenance chain ${DIM("— all dimensions in detail")}`, value: `__pick_show__` });
51
+ choices.push({ name: `Verify a record's completeness ${DIM("— check all 8 dimensions")}`, value: `__pick_verify__` });
52
+ }
53
+ choices.push({ name: `Create a new governance record ${DIM("— start a new approval chain")}`, value: `ges governance add` });
54
+ if (records.length === 0) {
55
+ choices.length = 0;
56
+ choices.push({ name: `Create a new governance record ${DIM("— start a new approval chain")}`, value: `ges governance add` });
57
+ }
58
+ choices.push({ name: `${YELLOW("Exit")} ${DIM("— return to terminal")}`, value: `exit` });
59
+ divider();
60
+ label("What would you like to do next?");
61
+ const answer = await select({
62
+ message: "Choose your next action:",
63
+ choices,
64
+ });
65
+ if (answer === "exit") {
66
+ blank();
67
+ return;
68
+ }
69
+ let cmd = answer;
70
+ if (answer === "__pick_show__" || answer === "__pick_verify__") {
71
+ let recordChoice;
72
+ if (records.length === 1) {
73
+ recordChoice = records[0].id;
74
+ }
75
+ else {
76
+ recordChoice = await select({
77
+ message: "Select a record:",
78
+ choices: records.map(r => ({
79
+ name: `${r.system_name} ${GRAY(`(${r.status}, ${r.risk_level})`)}`,
80
+ value: r.id,
81
+ })),
82
+ });
83
+ }
84
+ const sub = answer === "__pick_show__" ? "show" : "verify";
85
+ cmd = `ges governance ${sub} ${recordChoice}`;
86
+ }
87
+ blank();
88
+ info("Running", GREEN(cmd));
89
+ divider();
90
+ blank();
91
+ const { execSync } = await import("node:child_process");
92
+ try {
93
+ execSync(cmd, { stdio: "inherit" });
94
+ }
95
+ catch {
96
+ process.exit(1);
97
+ }
98
+ }
35
99
  export const governanceCommand = new Command("governance")
36
100
  .description("Manage governance approval provenance chains")
37
101
  .action(async () => {
@@ -332,12 +396,13 @@ export const governanceCommand = new Command("governance")
332
396
  }))
333
397
  .addCommand(new Command("list")
334
398
  .description("List all governance records")
335
- .action(() => {
399
+ .action(async () => {
336
400
  const root = ensureGESInitialized();
337
401
  const records = loadGovernanceRecords(root);
338
402
  if (records.length === 0) {
339
403
  info("No governance records found.");
340
404
  console.log(` ${DIM("Create one with:")} ${GREEN("ges governance add")}\n`);
405
+ await showGovernanceNextAction(root, records);
341
406
  return;
342
407
  }
343
408
  blank();
@@ -347,11 +412,12 @@ export const governanceCommand = new Command("governance")
347
412
  printRecordSummary(r);
348
413
  console.log();
349
414
  });
415
+ await showGovernanceNextAction(root, records);
350
416
  }))
351
417
  .addCommand(new Command("show")
352
418
  .description("Show full provenance chain for a governance record")
353
419
  .argument("<id>", "Record ID or system name")
354
- .action((id) => {
420
+ .action(async (id) => {
355
421
  const root = ensureGESInitialized();
356
422
  const record = findGovernanceRecord(root, id);
357
423
  if (!record) {
@@ -494,11 +560,12 @@ export const governanceCommand = new Command("governance")
494
560
  }
495
561
  console.log(`\n Created: ${record.created_at} by ${record.created_by}`);
496
562
  console.log(` Updated: ${record.updated_at} by ${record.updated_by} (v${record.record_version})\n`);
563
+ await showGovernanceNextAction(root, [record], record.id);
497
564
  }))
498
565
  .addCommand(new Command("verify")
499
566
  .description("Verify the provenance chain completeness of a governance record")
500
567
  .argument("<id>", "Record ID or system name")
501
- .action((id) => {
568
+ .action(async (id) => {
502
569
  const root = ensureGESInitialized();
503
570
  const record = findGovernanceRecord(root, id);
504
571
  if (!record) {
@@ -543,6 +610,7 @@ export const governanceCommand = new Command("governance")
543
610
  result.warnings.forEach(w => console.log(` ${YELLOW("△")} ${w}`));
544
611
  }
545
612
  console.log();
613
+ await showGovernanceNextAction(root, [record], record.id);
546
614
  }))
547
615
  .addCommand(new Command("delete")
548
616
  .description("Delete a governance record")
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.5.3",
7
- "@greenarmor/ges-cicd-generator": "1.5.3",
8
- "@greenarmor/ges-compliance-engine": "1.5.3",
9
- "@greenarmor/ges-core": "1.5.3",
10
- "@greenarmor/ges-doc-generator": "1.5.3",
11
- "@greenarmor/ges-git-hooks": "1.5.3",
12
- "@greenarmor/ges-mcp-server": "1.5.3",
13
- "@greenarmor/ges-policy-engine": "1.5.3",
14
- "@greenarmor/ges-report-generator": "1.5.3",
15
- "@greenarmor/ges-rules-engine": "1.5.3",
16
- "@greenarmor/ges-scanner-integration": "1.5.3",
17
- "@greenarmor/ges-scoring-engine": "1.5.3",
18
- "@greenarmor/ges-web-dashboard": "1.5.3",
6
+ "@greenarmor/ges-audit-engine": "1.5.4",
7
+ "@greenarmor/ges-cicd-generator": "1.5.4",
8
+ "@greenarmor/ges-compliance-engine": "1.5.4",
9
+ "@greenarmor/ges-core": "1.5.4",
10
+ "@greenarmor/ges-doc-generator": "1.5.4",
11
+ "@greenarmor/ges-git-hooks": "1.5.4",
12
+ "@greenarmor/ges-mcp-server": "1.5.4",
13
+ "@greenarmor/ges-policy-engine": "1.5.4",
14
+ "@greenarmor/ges-report-generator": "1.5.4",
15
+ "@greenarmor/ges-rules-engine": "1.5.4",
16
+ "@greenarmor/ges-scanner-integration": "1.5.4",
17
+ "@greenarmor/ges-scoring-engine": "1.5.4",
18
+ "@greenarmor/ges-web-dashboard": "1.5.4",
19
19
  "chalk": "^5.6.2",
20
20
  "commander": "^13.0.0"
21
21
  },
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "type": "module",
62
62
  "types": "./dist/index.d.ts",
63
- "version": "1.5.3",
63
+ "version": "1.5.4",
64
64
  "scripts": {
65
65
  "build": "tsc",
66
66
  "clean": "rm -rf dist tsconfig.tsbuildinfo",