🚀 Socket Launch Week Day 4:Socket MCP Adds Org Alerts, Threat Feed Review, and Package Inspection.Learn more
Sign In

@greenarmor/ges

Package Overview
Dependencies
Maintainers
1
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@greenarmor/ges - npm Package Compare versions

Comparing version
1.4.0
to
1.4.1
+37
dist/utils/ui.d.ts
import chalk from "chalk";
declare const DIM: import("chalk").ChalkInstance;
declare const BOLD: import("chalk").ChalkInstance;
declare const GREEN: import("chalk").ChalkInstance;
declare const RED: import("chalk").ChalkInstance;
declare const YELLOW: import("chalk").ChalkInstance;
declare const CYAN: import("chalk").ChalkInstance;
declare const MAGENTA: import("chalk").ChalkInstance;
declare const GRAY: import("chalk").ChalkInstance;
declare const icons: {
success: string;
error: string;
warn: string;
info: string;
arrow: string;
bullet: string;
check: string;
cross: string;
dash: string;
};
export declare function banner(title: string, subtitle?: string): void;
export declare function divider(width?: number): void;
export declare function blank(): void;
export declare function success(message: string, detail?: string): void;
export declare function error(message: string, detail?: string): void;
export declare function warn(message: string, detail?: string): void;
export declare function info(message: string, detail?: string): void;
export declare function step(n: number, total: number, message: string): void;
export declare function kv(key: string, value: string, indent?: number): void;
export declare function label(text: string, color?: typeof GREEN): void;
export declare function item(text: string, value?: string): void;
export declare function group(title: string, lines: string[]): void;
export declare function progressBar(current: number, total: number, width?: number): string;
export declare function statusBadge(status: string): string;
export declare function severityBadge(severity: string): string;
export declare function gradeColor(grade: string): string;
export { chalk, icons, DIM, BOLD, GREEN, RED, YELLOW, CYAN, MAGENTA, GRAY };
import chalk from "chalk";
const DIM = chalk.dim;
const BOLD = chalk.bold;
const GREEN = chalk.green;
const RED = chalk.red;
const YELLOW = chalk.yellow;
const CYAN = chalk.cyan;
const MAGENTA = chalk.magenta;
const GRAY = chalk.gray;
const icons = {
success: GREEN("✓"),
error: RED("✕"),
warn: YELLOW("!"),
info: CYAN("○"),
arrow: GRAY("→"),
bullet: GRAY("•"),
check: GREEN("✓"),
cross: RED("✕"),
dash: GRAY("—"),
};
export function banner(title, subtitle) {
const line = "═".repeat(52);
console.log();
console.log(CYAN(BOLD(` ${title}`)));
if (subtitle) {
console.log(DIM(` ${subtitle}`));
}
console.log(GRAY(` ${line}`));
console.log();
}
export function divider(width = 52) {
console.log(GRAY(` ${"─".repeat(width)}`));
}
export function blank() {
console.log();
}
export function success(message, detail) {
console.log(` ${icons.success} ${GREEN(message)}${detail ? DIM(` ${detail}`) : ""}`);
}
export function error(message, detail) {
console.error(` ${icons.error} ${RED(message)}${detail ? DIM(` ${detail}`) : ""}`);
}
export function warn(message, detail) {
console.log(` ${icons.warn} ${YELLOW(message)}${detail ? DIM(` ${detail}`) : ""}`);
}
export function info(message, detail) {
console.log(` ${icons.info} ${CYAN(message)}${detail ? DIM(` ${detail}`) : ""}`);
}
export function step(n, total, message) {
const counter = DIM(`[${n}/${total}]`);
console.log(`\n ${counter} ${BOLD(message)}`);
console.log(GRAY(` ${"─".repeat(40)}`));
}
export function kv(key, value, indent = 4) {
const pad = Math.max(key.length, 16);
console.log(`${" ".repeat(indent)}${DIM(key.padEnd(pad))} ${value}`);
}
export function label(text, color = CYAN) {
console.log(`\n ${color(BOLD(text))}`);
}
export function item(text, value) {
const v = value ? DIM(GRAY(` ${value}`)) : "";
console.log(` ${icons.bullet} ${text}${v}`);
}
export function group(title, lines) {
console.log(`\n ${BOLD(title)}`);
for (const line of lines) {
console.log(` ${icons.bullet} ${line}`);
}
}
export function progressBar(current, total, width = 30) {
const pct = Math.round((current / total) * 100);
const filled = Math.round((current / total) * width);
const empty = width - filled;
const bar = GREEN("█".repeat(filled)) + GRAY("░".repeat(empty));
return `${bar} ${pct}%`;
}
export function statusBadge(status) {
const badges = {
pass: GREEN("● PASS"),
fail: RED("● FAIL"),
warning: YELLOW("● WARN"),
"not-implemented": GRAY("○ N/I"),
"not-applicable": CYAN("◐ N/A"),
approved: GREEN("● APPROVED"),
rejected: RED("✕ REJECTED"),
conditional: YELLOW("◔ CONDITIONAL"),
"pending-review": YELLOW("◐ PENDING"),
draft: GRAY("○ DRAFT"),
expired: RED("⚠ EXPIRED"),
valid: GREEN("✓ VALID"),
};
return badges[status] || GRAY(`○ ${status.toUpperCase()}`);
}
export function severityBadge(severity) {
const badges = {
critical: RED(BOLD("CRITICAL")),
high: RED("HIGH"),
medium: YELLOW("MEDIUM"),
low: CYAN("LOW"),
};
return badges[severity] || GRAY(severity.toUpperCase());
}
export function gradeColor(grade) {
if (grade === "A")
return GREEN(BOLD(grade));
if (grade === "B")
return CYAN(BOLD(grade));
if (grade === "C")
return YELLOW(BOLD(grade));
if (grade === "D")
return MAGENTA(BOLD(grade));
return RED(BOLD(grade));
}
export { chalk, icons, DIM, BOLD, GREEN, RED, YELLOW, CYAN, MAGENTA, GRAY };
+28
-19

@@ -8,2 +8,3 @@ import { Command } from "commander";

import { showNextStepsMenu } from "../utils/next-steps.js";
import { banner, divider, blank, success, warn, info, severityBadge, BOLD, DIM, CYAN, RED, YELLOW, GRAY } from "../utils/ui.js";
import * as fs from "node:fs";

@@ -19,5 +20,6 @@ import * as path from "node:path";

const config = readJsonFile(path.join(root, ".ges", "config.json"));
console.log("\n GESF Compliance Audit");
console.log(" ────────────────────\n");
console.log(" Scanning project files...");
if (!options.json) {
banner("GESF Compliance Audit", options.incremental ? "Incremental scan" : "Full project scan");
info("Scanning project files...");
}
let rawFindings;

@@ -32,3 +34,4 @@ let scannedFiles;

scannedFiles = result.scannedFiles;
console.log(` Scanned ${scannedFiles} files (${result.changedFiles} changed)`);
if (!options.json)
success("Scan complete", `${scannedFiles} files (${result.changedFiles} changed)`);
}

@@ -39,6 +42,8 @@ else {

scannedFiles = result.scannedFiles;
console.log(` Scanned ${scannedFiles} files`);
if (!options.json)
success("Scan complete", `${scannedFiles} files`);
}
const findings = deduplicateFindings(rawFindings);
console.log("");
if (!options.json)
blank();
const configFrameworks = (config?.frameworks || ["GDPR", "OWASP"]);

@@ -83,3 +88,4 @@ const projectPacks = getPacksForProjectType(config?.project_type || "generic-web-application");

const passCount = overrides.filter(o => o.status === "pass").length;
console.log(` Control overrides: ${naCount} not-applicable, ${passCount} pre-verified\n`);
if (!options.json)
info("Control overrides", `${naCount} not-applicable, ${passCount} pre-verified`);
}

@@ -92,19 +98,19 @@ if (options.json) {

}
console.log(" ── Findings ─────────────────────\n");
console.log(` Total findings: ${findings.length}`);
console.log(` Critical: ${critical.length} High: ${high.length} Medium: ${medium.length} Low: ${low.length}\n`);
console.log(` ${BOLD("Findings")}`);
divider(40);
console.log(` ${DIM("Total")} ${findings.length}`);
console.log(` ${RED(`Critical ${critical.length}`)} ${RED(`High ${high.length}`)} ${YELLOW(`Medium ${medium.length}`)} ${CYAN(`Low ${low.length}`)}\n`);
if (findings.length > 0) {
const grouped = groupByCategory(findings);
for (const [category, categoryFindings] of Object.entries(grouped)) {
console.log(` [${category.toUpperCase()}]`);
console.log(` ${BOLD(category.toUpperCase())}`);
for (const f of categoryFindings.slice(0, 10)) {
const sev = f.severity === "critical" ? "CRIT" : f.severity === "high" ? "HIGH" : f.severity === "medium" ? "MED " : "LOW ";
const loc = f.file !== "project" ? ` (${f.file}${f.line ? ":" + f.line : ""})` : "";
console.log(` [${sev}] ${f.title}${loc}`);
const loc = f.file !== "project" ? ` ${DIM(`(${f.file}${f.line ? ":" + f.line : ""})`)}` : "";
console.log(` ${severityBadge(f.severity).padEnd(10)} ${f.title}${loc}`);
if (f.evidence && f.file !== "project") {
console.log(` ${f.evidence.slice(0, 100)}`);
console.log(` ${GRAY(f.evidence.slice(0, 100))}`);
}
}
if (categoryFindings.length > 10) {
console.log(` ... and ${categoryFindings.length - 10} more`);
console.log(` ${DIM(`... and ${categoryFindings.length - 10} more`)}`);
}

@@ -115,8 +121,11 @@ console.log("");

else {
console.log(" ✓ No security or compliance issues found in source code.\n");
success("No security or compliance issues found in source code.");
blank();
}
console.log(" ── Compliance Score ──────────────");
console.log(` ${BOLD("Compliance Score")}`);
divider(40);
console.log(formatScoreOutput(scoreData));
if (critical.length > 0) {
console.log(" !! Critical issues must be resolved before deployment. !!\n");
warn("Critical issues must be resolved before deployment.");
blank();
}

@@ -123,0 +132,0 @@ recordActivity(root, {

@@ -6,2 +6,3 @@ import { Command } from "commander";

import { showNextStepsMenu } from "../utils/next-steps.js";
import { banner, success, warn, error, blank, progressBar, BOLD, DIM, GREEN, RED, YELLOW } from "../utils/ui.js";
import * as fs from "node:fs";

@@ -12,4 +13,3 @@ import * as path from "node:path";

.action(async () => {
console.log("\n GESF Doctor - Diagnostic Check");
console.log(" ─────────────────────────────\n");
banner("GESF Doctor", "Diagnostic health check");
const checks = [];

@@ -87,9 +87,21 @@ const root = findProjectRoot();

checks.push({ name: "GESF Version", status: "OK", detail: CLI_VERSION });
const okCount = checks.filter(c => c.status === "OK").length;
const warnCount = checks.filter(c => c.status === "WARN" || c.status === "MISSING").length;
const failCount = checks.filter(c => c.status === "FAIL").length;
console.log(` ${BOLD("Health Score")} ${progressBar(okCount, checks.length, 24)}`);
console.log(` ${DIM("Checks")} ${GREEN(`${okCount} ok`)} ${YELLOW(`${warnCount} warn`)} ${RED(`${failCount} fail`)}`);
blank();
for (const check of checks) {
const icon = check.status === "OK" ? "✓" : check.status === "WARN" ? "!" : "✗";
const line = ` [${icon}] ${check.name}`;
console.log(line + (check.detail ? ` - ${check.detail}` : ""));
if (check.status === "OK") {
success(check.name, check.detail);
}
else if (check.status === "WARN" || check.status === "MISSING") {
warn(check.name, check.detail);
}
else {
error(check.name, check.detail);
}
}
console.log("");
blank();
await showNextStepsMenu("doctor");
});
import { Command } from "commander";
import { ensureGESInitialized } from "../utils/project.js";
import { input, select } from "../utils/prompts.js";
import { banner, divider, blank, success, info, kv, statusBadge, severityBadge, BOLD, DIM, GREEN, RED, YELLOW, GRAY, } from "../utils/ui.js";
import { loadGovernanceRecords, createGovernanceRecord, addGovernanceRecord, findGovernanceRecord, setGovernanceApproval, addGovernanceEvidence, createEvidenceRef, verifyGovernanceRecord, deleteGovernanceRecord, setGovernanceRiskAssessment, setGovernancePolicyBasis, setGovernanceReviewCycle, setGovernanceDataInventory, setGovernanceComplianceLinks, setGovernanceCommittee, } from "@greenarmor/ges-core";

@@ -22,13 +23,13 @@ import { recordActivity } from "@greenarmor/ges-core";

function printRecordSummary(record) {
const badge = STATUS_BADGE[record.status] || "?";
console.log(` ${badge} ${record.id} ${record.system_name}`);
console.log(` Type: ${record.system_type} | Risk: ${RISK_COLOR[record.risk_level] || record.risk_level} | Status: ${record.status}`);
console.log(` ${statusBadge(record.status)} ${BOLD(record.system_name)}`);
console.log(` ${DIM("ID")} ${record.id}`);
console.log(` ${DIM("Type")} ${record.system_type} ${GRAY("|")} ${DIM("Risk")} ${severityBadge(record.risk_level)}`);
if (record.approval) {
console.log(` Approved by: ${record.approval.approver_name} (${record.approval.approver_role})`);
console.log(` Valid: ${record.approval.valid_from} → ${record.approval.valid_until || "indefinite"}`);
console.log(` ${DIM("By")} ${record.approval.approver_name} (${record.approval.approver_role})`);
console.log(` ${DIM("Valid")} ${record.approval.valid_from} ${GRAY("→")} ${record.approval.valid_until || "indefinite"}`);
}
else {
console.log(` Approval: NOT RECORDED`);
console.log(` ${DIM("By")} ${GRAY("NOT RECORDED")}`);
}
console.log(` Evidence: ${record.evidence.length} reference(s)`);
console.log(` ${DIM("Ev")} ${record.evidence.length} reference(s)`);
}

@@ -82,9 +83,11 @@ export const governanceCommand = new Command("governance")

addGovernanceRecord(root, record);
console.log(`\n [✓] Governance record created`);
console.log(` ID: ${record.id}`);
blank();
success("Governance record created");
kv("ID", record.id, 6);
console.log();
printRecordSummary(record);
console.log(`\n Next steps:`);
console.log(` ges governance approve ${record.id} — Record approval decision`);
console.log(` ges governance evidence ${record.id} — Add evidence reference`);
console.log(` ges governance verify ${record.id} — Verify provenance chain\n`);
console.log(`\n ${DIM("Next steps:")}`);
console.log(` ${GRAY("–")} ${GREEN("ges governance approve")} ${record.id} ${DIM("Record approval decision")}`);
console.log(` ${GRAY("–")} ${GREEN("ges governance evidence")} ${record.id} ${DIM("Add evidence reference")}`);
console.log(` ${GRAY("–")} ${GREEN("ges governance verify")} ${record.id} ${DIM("Verify provenance chain")}\n`);
recordActivity(root, {

@@ -153,6 +156,8 @@ source: "cli",

}
console.log(`\n [✓] Approval recorded for ${updated.system_name}`);
console.log(` Decision: ${decision.toUpperCase()}`);
console.log(` Approver: ${approverName} (${approverRole})`);
console.log(` Valid: ${validFrom} → ${validUntil || "indefinite"}\n`);
blank();
success("Approval recorded", `for ${updated.system_name}`);
kv("Decision", decision.toUpperCase(), 6);
kv("Approver", `${approverName} (${approverRole})`, 6);
kv("Valid", `${validFrom} → ${validUntil || "indefinite"}`, 6);
console.log();
recordActivity(root, {

@@ -229,6 +234,9 @@ source: "cli",

}
console.log(`\n [✓] Evidence added to ${updated.system_name}`);
console.log(` ${evidence.title}`);
console.log(` Source: ${evidence.source_system} | Ref: ${evidence.reference}`);
console.log(` Total evidence: ${updated.evidence.length} reference(s)\n`);
blank();
success("Evidence added", `to ${updated.system_name}`);
console.log(` ${BOLD(evidence.title)}`);
kv("Source", evidence.source_system, 6);
kv("Ref", evidence.reference, 6);
kv("Total", `${updated.evidence.length} reference(s)`, 6);
console.log();
recordActivity(root, {

@@ -250,10 +258,12 @@ source: "cli",

if (records.length === 0) {
console.log(`\n No governance records found.`);
console.log(` Create one with: ges governance add\n`);
info("No governance records found.");
console.log(` ${DIM("Create one with:")} ${GREEN("ges governance add")}\n`);
return;
}
console.log(`\n Governance Records (${records.length}):\n`);
blank();
console.log(` ${BOLD("Governance Records")} ${GRAY(`(${records.length})`)}`);
console.log();
records.forEach(r => {
printRecordSummary(r);
console.log("");
console.log();
});

@@ -419,30 +429,39 @@ }))

const result = verifyGovernanceRecord(record);
console.log(`\n ═══════════════════════════════════════════════════`);
console.log(` VERIFICATION: ${record.system_name}`);
console.log(` ═══════════════════════════════════════════════════\n`);
console.log(` Overall: ${result.valid ? "✓ VALID" : "✕ ISSUES FOUND"}`);
console.log(` Approval Status: ${result.approval_status.toUpperCase()}`);
banner("VERIFICATION", record.system_name);
const overallText = result.valid ? GREEN(BOLD("✓ VALID")) : RED(BOLD("✕ ISSUES FOUND"));
console.log(` ${DIM("Overall:")} ${overallText}`);
console.log(` ${DIM("Approval:")} ${statusBadge(result.approval_status)}`);
if (result.days_until_expiry !== null) {
const dayLabel = result.days_until_expiry < 0 ? `${Math.abs(result.days_until_expiry)} days AGO` : `${result.days_until_expiry} days remaining`;
console.log(` Expiry: ${dayLabel}`);
const dayLabel = result.days_until_expiry < 0
? RED(`${Math.abs(result.days_until_expiry)} days AGO`)
: result.days_until_expiry <= 30
? YELLOW(`${result.days_until_expiry} days remaining`)
: GREEN(`${result.days_until_expiry} days remaining`);
console.log(` ${DIM("Expiry:")} ${dayLabel}`);
}
console.log(` Evidence Count: ${result.completeness.evidence_count}`);
console.log(`\n Completeness Checklist:`);
console.log(` ${result.completeness.has_approval ? "✓" : "✕"} Approval Decision`);
console.log(` ${result.completeness.has_risk_assessment ? "✓" : "✕"} Risk Assessment`);
console.log(` ${result.completeness.has_policy_basis ? "✓" : "✕"} Policy Basis`);
console.log(` ${result.completeness.has_evidence ? "✓" : "✕"} Evidence Chain`);
console.log(` ${result.completeness.has_review_cycle ? "✓" : "△"} Review Cycle`);
console.log(` ${result.completeness.has_data_inventory ? "✓" : "△"} Data Inventory`);
console.log(` ${result.completeness.has_compliance_links ? "✓" : "△"} Compliance Links`);
console.log(` ${result.completeness.is_current ? "✓" : "✕"} Currently Valid`);
console.log(` ${DIM("Evidence:")} ${result.completeness.evidence_count} reference(s)`);
console.log(`\n ${BOLD("Completeness Checklist")}`);
divider(40);
const check = (ok, label, isWarning = false) => {
const icon = ok ? GREEN("✓") : isWarning ? YELLOW("△") : RED("✕");
const text = ok ? label : isWarning ? YELLOW(label) : RED(label);
console.log(` ${icon} ${text}`);
};
check(result.completeness.has_approval, "Approval Decision");
check(result.completeness.has_risk_assessment, "Risk Assessment");
check(result.completeness.has_policy_basis, "Policy Basis");
check(result.completeness.has_evidence, "Evidence Chain");
check(result.completeness.has_review_cycle, "Review Cycle", true);
check(result.completeness.has_data_inventory, "Data Inventory", true);
check(result.completeness.has_compliance_links, "Compliance Links", true);
check(result.completeness.is_current, "Currently Valid");
if (result.issues.length > 0) {
console.log(`\n BLOCKING ISSUES:`);
result.issues.forEach(i => console.log(` ✕ ${i}`));
console.log(`\n ${RED(BOLD("BLOCKING ISSUES"))}`);
result.issues.forEach(i => console.log(` ${RED("✕")} ${i}`));
}
if (result.warnings.length > 0) {
console.log(`\n WARNINGS:`);
result.warnings.forEach(w => console.log(` △ ${w}`));
console.log(`\n ${YELLOW(BOLD("WARNINGS"))}`);
result.warnings.forEach(w => console.log(` ${YELLOW("△")} ${w}`));
}
console.log("");
console.log();
}))

@@ -463,3 +482,5 @@ .addCommand(new Command("delete")

if (deleted) {
console.log(`\n [✓] Deleted governance record: ${record.system_name} (${record.id})\n`);
blank();
success("Deleted governance record", `${record.system_name} (${record.id})`);
console.log();
recordActivity(root, {

@@ -517,4 +538,8 @@ source: "cli",

}
console.log(`\n [✓] Risk assessment linked to ${updated.system_name}`);
console.log(` Assessor: ${assessor} | Score: ${score} | Residual: ${residual}\n`);
blank();
success("Risk assessment linked", `to ${updated.system_name}`);
kv("Assessor", assessor, 6);
kv("Score", score, 6);
kv("Residual", residual, 6);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Risk assessment added: ${updated.system_name}`, description: `Risk assessment by ${assessor} linked to ${updated.system_name}. Score: ${score}, Residual: ${residual}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });

@@ -555,4 +580,7 @@ }))

}
console.log(`\n [✓] Policy basis documented for ${updated.system_name}`);
console.log(` ${policyName} (${policyId} v${version}) — ${standard}\n`);
blank();
success("Policy basis documented", `for ${updated.system_name}`);
kv("Policy", `${policyName} (${policyId} v${version})`, 6);
kv("Standard", standard, 6);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Policy basis added: ${updated.system_name}`, description: `Policy ${policyName} (${policyId} v${version}) documented for ${updated.system_name}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });

@@ -595,4 +623,7 @@ }))

}
console.log(`\n [✓] Review cycle set for ${updated.system_name}`);
console.log(` Frequency: ${frequency} | Next review: ${nextReview}\n`);
blank();
success("Review cycle set", `for ${updated.system_name}`);
kv("Frequency", frequency, 6);
kv("Next review", nextReview, 6);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Review cycle set: ${updated.system_name}`, description: `Review cycle (${frequency}) set for ${updated.system_name}. Next review: ${nextReview}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });

@@ -631,3 +662,5 @@ }))

}
console.log(`\n [✓] Data inventory documented for ${updated.system_name}\n`);
blank();
success("Data inventory documented", `for ${updated.system_name}`);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Data inventory added: ${updated.system_name}`, description: `Data inventory documented for ${updated.system_name}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });

@@ -667,4 +700,7 @@ }))

}
console.log(`\n [✓] Committee approval recorded for ${updated.system_name}`);
console.log(` ${committeeName} — ${meetingDate} (${meetingRef})\n`);
blank();
success("Committee approval recorded", `for ${updated.system_name}`);
kv("Committee", committeeName, 6);
kv("Meeting", `${meetingDate} (${meetingRef})`, 6);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Committee approval added: ${updated.system_name}`, description: `Committee ${committeeName} (${meetingRef}) recorded for ${updated.system_name}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });

@@ -698,4 +734,6 @@ }))

}
console.log(`\n [✓] Compliance links mapped for ${updated.system_name}\n`);
blank();
success("Compliance links mapped", `for ${updated.system_name}`);
console.log();
recordActivity(root, { source: "cli", action: "control_override", title: `Compliance links added: ${updated.system_name}`, description: `Compliance frameworks mapped for ${updated.system_name}.`, details: { governance_record_id: updated.id }, actor_name: options.actor, actor_role: options.actorRole });
}));
import { Command } from "commander";
import { input, select, checkbox } from "../utils/prompts.js";
import { banner, divider, blank, success, error, warn, info, step, kv, label, BOLD, CYAN, GREEN, GRAY, } from "../utils/ui.js";
import { PROJECT_TYPES, FRAMEWORKS, DEFAULT_FRAMEWORKS, GES_DIR, COMPLIANCE_DIR, SECURITY_DIR, CONTROLS_DIR, POLICIES_DIR, CHECKLISTS_DIR, DOCS_DIR, REPORTS_DIR, } from "@greenarmor/ges-core";

@@ -21,12 +22,11 @@ import { CLI_VERSION } from "../utils/version.js";

.action(async (options) => {
console.log("\n Green Engineering Standard Framework (GESF) v" + CLI_VERSION);
console.log(" ─────────────────────────────────────────────\n");
banner(`Green Engineering Standard Framework`, `v${CLI_VERSION}`);
const gesDir = path.join(process.cwd(), GES_DIR);
if (fs.existsSync(gesDir)) {
if (!options.force) {
console.error(" Error: GESF is already initialized in this project.");
console.error(" Use 'ges init --force' to re-initialize.\n");
error("GESF is already initialized in this project.");
info("Use", "ges init --force to re-initialize.\n");
process.exit(1);
}
console.log(" ⚠ Re-initializing GESF (existing files will be overwritten)...\n");
warn("Re-initializing GESF", "existing files will be overwritten\n");
fs.rmSync(gesDir, { recursive: true, force: true });

@@ -52,3 +52,3 @@ }

if (selectedFrameworks.length === 0) {
console.error(" Error: At least one framework must be selected.");
error("At least one framework must be selected.");
process.exit(1);

@@ -85,4 +85,4 @@ }

if (options.country && !countryInfo && countryCode !== "EU") {
console.warn(` ⚠ Country code '${options.country}' not recognized. No privacy pack will be auto-installed.`);
console.warn(` Available codes: ${PRIVACY_COUNTRIES.map(c => c.code).join(", ")}, EU`);
warn(`Country code '${options.country}' not recognized.`, "No privacy pack will be auto-installed.");
info("Available codes:", `${PRIVACY_COUNTRIES.map(c => c.code).join(", ")}, EU`);
}

@@ -199,27 +199,35 @@ // --- Optional: Additional privacy packs ---

}
console.log(" ✓ Project structure created");
console.log(" ✓ Configuration files generated");
console.log(" ✓ Compliance documents created");
console.log(" ✓ Security documents created");
blank();
step(1, 4, "Creating project structure");
success("Project structure created");
success("Configuration files generated");
success("Compliance documents created");
success("Security documents created");
if (countryInfo) {
console.log(` ✓ Country privacy pack auto-installed: ${countryInfo.packId} (${countryInfo.name})`);
success("Country privacy pack auto-installed", `${countryInfo.packId} (${countryInfo.name})`);
}
else if (countryCode === "EU") {
console.log(" ✓ EU GDPR privacy pack auto-installed");
success("EU GDPR privacy pack auto-installed");
}
if (additionalPacks.length > 0) {
console.log(` ✓ Additional privacy packs installed: ${additionalPacks.join(", ")}`);
success("Additional privacy packs installed", additionalPacks.join(", "));
}
console.log(" ✓ Control packs installed:", packs.map(p => p.id).join(", "));
console.log(" ✓ GitHub Actions workflows generated");
console.log(" ✓ Developer logs directory created (.dev-logs/)");
console.log(`\n GESF initialized for "${projectName}" (${projectType})`);
success("Control packs installed", packs.map(p => p.id).join(", "));
success("GitHub Actions workflows generated");
success("Developer logs directory created", ".dev-logs/");
blank();
step(2, 4, "Project summary");
blank();
console.log(` ${CYAN(BOLD("GESF initialized"))} for "${projectName}" (${projectType})`);
if (countryInfo) {
console.log(` Country: ${countryInfo.name} — ${countryInfo.lawName}`);
kv("Country", `${countryInfo.name} — ${countryInfo.lawName}`);
}
console.log(" Next steps:");
console.log(" 1. Review generated compliance documents");
console.log(" 2. Run 'ges audit' to evaluate your project");
console.log(" 3. Run 'ges score' to see your compliance score");
console.log(" 4. Add more packs with 'ges policy install <pack-id>'\n");
divider(40);
blank();
step(3, 4, "Next steps");
label("Quick start:");
console.log(` ${GRAY("1.")} Review generated compliance documents`);
console.log(` ${GRAY("2.")} Run ${GREEN("ges audit")} to evaluate your project`);
console.log(` ${GRAY("3.")} Run ${GREEN("ges score")} to see your compliance score`);
console.log(` ${GRAY("4.")} Add more packs with ${GREEN("ges policy install <pack-id>")}`);
recordActivity(process.cwd(), {

@@ -226,0 +234,0 @@ source: "cli",

@@ -6,2 +6,3 @@ import { Command } from "commander";

import { showNextStepsMenu } from "../utils/next-steps.js";
import { banner, blank, success, error, BOLD, CYAN, DIM, GRAY } from "../utils/ui.js";
import * as fs from "node:fs";

@@ -15,8 +16,7 @@ import * as path from "node:path";

.action(async () => {
console.log("\n Available Policy Packs:\n");
banner("Policy Packs", "Available compliance control packs");
const packs = getAllPacks();
for (const pack of packs) {
console.log(` ${pack.id.padEnd(15)} ${pack.name}`);
const indent = " ";
console.log(` ${indent} ${pack.controls.length} controls | ${pack.project_types.join(", ")}`);
console.log(` ${CYAN(BOLD(pack.id.padEnd(18)))} ${pack.name}`);
console.log(` ${DIM(`${pack.controls.length} controls`)} ${GRAY("|")} ${DIM(pack.project_types.join(", "))}`);
console.log("");

@@ -34,3 +34,3 @@ }

if (!pack) {
console.error(` Error: Pack '${packId}' not found. Available: ${listPackIds().join(", ")}`);
error(`Pack '${packId}' not found.`, `Available: ${listPackIds().join(", ")}`);
process.exit(1);

@@ -47,7 +47,9 @@ }

}
console.log(`\n ✓ Installed policy pack: ${pack.id} (${pack.controls.length} controls)`);
blank();
success("Installed policy pack", `${pack.id} (${pack.controls.length} controls)`);
if (frameworksAdded.length > 0) {
console.log(` ✓ Added ${frameworksAdded.join(", ")} to project frameworks in .ges/config.json`);
success("Updated project frameworks", frameworksAdded.join(", "));
}
console.log(" ✓ Dashboard will now reflect this pack's controls\n");
success("Dashboard will reflect this pack's controls");
blank();
recordActivity(root, {

@@ -69,3 +71,3 @@ source: "cli",

if (!fs.existsSync(packDir)) {
console.error(` Error: Pack '${packId}' is not installed.`);
error(`Pack '${packId}' is not installed.`);
process.exit(1);

@@ -84,3 +86,5 @@ }

}
console.log(`\n ✓ Removed policy pack: ${packId}\n`);
blank();
success("Removed policy pack", packId);
blank();
recordActivity(root, {

@@ -87,0 +91,0 @@ source: "cli",

@@ -6,2 +6,3 @@ import { Command } from "commander";

import { showNextStepsMenu } from "../utils/next-steps.js";
import { warn, info, blank, DIM } from "../utils/ui.js";
import * as path from "node:path";

@@ -16,3 +17,6 @@ export const scoreCommand = new Command("score")

if (!score || !score.frameworks || Object.keys(score.frameworks).length === 0) {
console.log("\n No compliance score available. Run 'ges audit' first.\n");
blank();
warn("No compliance score available.");
info("Run", "ges audit first.");
blank();
await showNextStepsMenu("score");

@@ -26,3 +30,3 @@ return;

console.log(formatScoreOutput(score));
console.log(` Last evaluated: ${score.evaluated_at}\n`);
console.log(` ${DIM("Last evaluated:")} ${score.evaluated_at}\n`);
}

@@ -29,0 +33,0 @@ recordActivity(root, {

import { select } from "./prompts.js";
const DIVIDER = " ─────────────────────────────────────────────";
import { divider, blank, label, info, GREEN } from "./ui.js";
function isInteractive() {

@@ -18,2 +18,3 @@ return process.stdin.isTTY === true && process.stdout.isTTY === true;

update: { label: "Check updates", value: "ges update", description: "Check for GESF updates" },
governance: { label: "Governance", value: "ges governance list", description: "View approval provenance chains" },
};

@@ -59,2 +60,4 @@ function buildSteps(exclude) {

return buildSteps(["update"]);
case "governance":
return buildSteps(["governance"]);
case "mcp-setup":

@@ -70,6 +73,6 @@ return buildSteps(["mcp-setup"]);

const steps = getNextStepsForCommand(command, context);
console.log(DIVIDER);
console.log(" What would you like to do next?\n");
divider();
label("What would you like to do next?");
const answer = await select({
message: "Select next action:",
message: "Choose your next action:",
choices: steps.map(step => ({

@@ -84,4 +87,6 @@ name: step.description ? `${step.label} — ${step.description}` : step.label,

}
console.log(`\n Running: ${answer}\n`);
console.log(DIVIDER + "\n");
blank();
info("Running", GREEN(answer));
divider();
blank();
const { execSync } = await import("node:child_process");

@@ -88,0 +93,0 @@ try {

@@ -10,3 +10,5 @@ export declare function input(options: {

value: T;
description?: string;
}[];
pageSize?: number;
}): Promise<T>;

@@ -19,3 +21,9 @@ export declare function checkbox<T = string>(options: {

checked?: boolean;
description?: string;
}[];
pageSize?: number;
}): Promise<T[]>;
export declare function confirm(options: {
message: string;
default?: boolean;
}): Promise<boolean>;
import * as readline from "node:readline";
import { chalk, DIM, GREEN, CYAN, GRAY } from "./ui.js";
function isInteractive() {

@@ -21,2 +22,13 @@ return process.stdin.isTTY === true && process.stdout.isTTY === true;

}
const selectTheme = {
prefix: { idle: chalk.gray("?"), done: chalk.green("✓") },
helpMode: "always",
};
const checkboxTheme = {
prefix: { idle: chalk.gray("?"), done: chalk.green("✓") },
helpMode: "always",
};
const inputTheme = {
prefix: { idle: chalk.gray("?"), done: chalk.green("✓") },
};
export async function input(options) {

@@ -31,5 +43,5 @@ if (!isInteractive()) {

const rl = createRL();
const suffix = options.default ? ` (${options.default})` : "";
const suffix = options.default ? DIM(` (${options.default})`) : "";
return new Promise((resolve) => {
rl.question(` ${options.message}${suffix}: `, (answer) => {
rl.question(` ${GRAY("?")} ${options.message}${suffix}${GRAY(":")} `, (answer) => {
rl.close();

@@ -46,11 +58,17 @@ resolve(answer.trim() || options.default || "");

if (inquirer) {
return inquirer.select({ message: options.message, choices: options.choices });
return inquirer.select({
message: options.message,
choices: options.choices,
theme: selectTheme,
pageSize: options.pageSize ?? 10,
});
}
console.log(`\n ${options.message}:\n`);
console.log(`\n ${CYAN(options.message)}:\n`);
options.choices.forEach((c, i) => {
console.log(` ${i + 1}) ${c.name}`);
const num = GRAY(`${String(i + 1).padStart(2)}.`);
console.log(` ${num} ${c.name}`);
});
const rl = createRL();
return new Promise((resolve) => {
rl.question(`\n Enter choice [1-${options.choices.length}]: `, (answer) => {
rl.question(`\n ${GRAY("Enter choice")} [1-${options.choices.length}]: `, (answer) => {
rl.close();

@@ -73,12 +91,18 @@ const num = parseInt(answer.trim(), 10);

if (inquirer) {
return inquirer.checkbox({ message: options.message, choices: options.choices });
return inquirer.checkbox({
message: options.message,
choices: options.choices,
theme: checkboxTheme,
pageSize: options.pageSize ?? 10,
});
}
console.log(`\n ${options.message} (comma-separated numbers):\n`);
console.log(`\n ${CYAN(options.message)} ${GRAY("(comma-separated numbers)")}\n`);
options.choices.forEach((c, i) => {
const marker = c.checked ? "[x]" : "[ ]";
console.log(` ${marker} ${i + 1}) ${c.name}`);
const marker = c.checked ? GREEN("[x]") : GRAY("[ ]");
const num = `${String(i + 1).padStart(2)}.`;
console.log(` ${marker} ${GRAY(num)} ${c.name}`);
});
const rl = createRL();
return new Promise((resolve) => {
rl.question(`\n Enter choices [1-${options.choices.length}]: `, (answer) => {
rl.question(`\n ${GRAY("Enter choices")} [1-${options.choices.length}]: `, (answer) => {
rl.close();

@@ -99,1 +123,28 @@ const trimmed = answer.trim();

}
export async function confirm(options) {
if (!isInteractive()) {
return options.default ?? false;
}
const inquirer = await getInquirer();
if (inquirer) {
return inquirer.confirm({
message: options.message,
default: options.default,
theme: inputTheme,
});
}
const suffix = options.default !== undefined ? ` (${options.default ? "Y/n" : "y/N"})` : " (y/n)";
const rl = createRL();
return new Promise((resolve) => {
rl.question(` ${GRAY("?")} ${options.message}${suffix}: `, (answer) => {
rl.close();
const trimmed = answer.trim().toLowerCase();
if (!trimmed) {
resolve(options.default ?? false);
}
else {
resolve(trimmed === "y" || trimmed === "yes");
}
});
});
}

@@ -6,15 +6,16 @@ {

"dependencies": {
"@greenarmor/ges-audit-engine": "1.4.0",
"@greenarmor/ges-cicd-generator": "1.4.0",
"@greenarmor/ges-compliance-engine": "1.4.0",
"@greenarmor/ges-core": "1.4.0",
"@greenarmor/ges-doc-generator": "1.4.0",
"@greenarmor/ges-git-hooks": "1.4.0",
"@greenarmor/ges-mcp-server": "1.4.0",
"@greenarmor/ges-policy-engine": "1.4.0",
"@greenarmor/ges-report-generator": "1.4.0",
"@greenarmor/ges-rules-engine": "1.4.0",
"@greenarmor/ges-scanner-integration": "1.4.0",
"@greenarmor/ges-scoring-engine": "1.4.0",
"@greenarmor/ges-web-dashboard": "1.4.0",
"@greenarmor/ges-audit-engine": "1.4.1",
"@greenarmor/ges-cicd-generator": "1.4.1",
"@greenarmor/ges-compliance-engine": "1.4.1",
"@greenarmor/ges-core": "1.4.1",
"@greenarmor/ges-doc-generator": "1.4.1",
"@greenarmor/ges-git-hooks": "1.4.1",
"@greenarmor/ges-mcp-server": "1.4.1",
"@greenarmor/ges-policy-engine": "1.4.1",
"@greenarmor/ges-report-generator": "1.4.1",
"@greenarmor/ges-rules-engine": "1.4.1",
"@greenarmor/ges-scanner-integration": "1.4.1",
"@greenarmor/ges-scoring-engine": "1.4.1",
"@greenarmor/ges-web-dashboard": "1.4.1",
"chalk": "^5.6.2",
"commander": "^13.0.0"

@@ -28,2 +29,5 @@ },

},
"optionalDependencies": {
"@inquirer/prompts": "^7.10.1"
},
"engines": {

@@ -58,3 +62,3 @@ "node": ">=20.0.0"

"types": "./dist/index.d.ts",
"version": "1.4.0",
"version": "1.4.1",
"scripts": {

@@ -61,0 +65,0 @@ "build": "tsc",