@sentriflow/cli 0.4.2 → 0.5.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.
Files changed (2) hide show
  1. package/dist/index.js +121 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12323,7 +12323,7 @@ function generateSarif(results, filePath, rules, options = {}, ipSummary) {
12323
12323
  tool: {
12324
12324
  driver: {
12325
12325
  name: "Sentriflow",
12326
- version: "0.4.2",
12326
+ version: "0.5.0",
12327
12327
  informationUri: "https://github.com/sentriflow/sentriflow",
12328
12328
  rules: sarifRules,
12329
12329
  // SEC-007: Include CWE taxonomy when rules reference it
@@ -12483,7 +12483,7 @@ function generateMultiFileSarif(fileResults, rules, options = {}) {
12483
12483
  tool: {
12484
12484
  driver: {
12485
12485
  name: "Sentriflow",
12486
- version: "0.4.2",
12486
+ version: "0.5.0",
12487
12487
  informationUri: "https://github.com/sentriflow/sentriflow",
12488
12488
  rules: sarifRules,
12489
12489
  // SEC-007: Include CWE taxonomy when rules reference it
@@ -12527,6 +12527,103 @@ function generateMultiFileSarif(fileResults, rules, options = {}) {
12527
12527
  return JSON.stringify(report, null, 2);
12528
12528
  }
12529
12529
 
12530
+ // src/human.ts
12531
+ var COLORS = {
12532
+ red: "\x1B[31m",
12533
+ yellow: "\x1B[33m",
12534
+ blue: "\x1B[34m",
12535
+ gray: "\x1B[90m",
12536
+ bold: "\x1B[1m",
12537
+ reset: "\x1B[0m"
12538
+ };
12539
+ var SEVERITY_COLORS = {
12540
+ error: COLORS.red,
12541
+ warning: COLORS.yellow,
12542
+ info: COLORS.blue
12543
+ };
12544
+ function countSeverities(results) {
12545
+ const counts = { error: 0, warning: 0, info: 0, total: 0 };
12546
+ for (const r of results) {
12547
+ if (!r.passed) {
12548
+ if (r.level === "error" || r.level === "warning" || r.level === "info") {
12549
+ counts[r.level]++;
12550
+ }
12551
+ counts.total++;
12552
+ }
12553
+ }
12554
+ return counts;
12555
+ }
12556
+ function formatFinding(result, color) {
12557
+ const line = result.loc?.startLine ?? 0;
12558
+ const col = 1;
12559
+ const location = `${line}:${col}`.padEnd(8);
12560
+ const severityColor = color ? SEVERITY_COLORS[result.level] ?? "" : "";
12561
+ const reset = color ? COLORS.reset : "";
12562
+ const severityText = result.level.padEnd(7);
12563
+ const severity = `${severityColor}${severityText}${reset}`;
12564
+ const ruleColor = color ? COLORS.gray : "";
12565
+ const ruleId = `${ruleColor}${result.ruleId}${reset}`;
12566
+ return ` ${location} ${severity} ${result.message} ${ruleId}`;
12567
+ }
12568
+ function formatSummary(counts, color) {
12569
+ if (counts.total === 0) {
12570
+ const check = color ? `${COLORS.bold}\u2714${COLORS.reset}` : "\u2714";
12571
+ return `
12572
+ ${check} No problems found
12573
+ `;
12574
+ }
12575
+ const x = color ? `${COLORS.red}\u2716${COLORS.reset}` : "\u2716";
12576
+ const parts = [];
12577
+ if (counts.error > 0) {
12578
+ parts.push(`${counts.error} error${counts.error !== 1 ? "s" : ""}`);
12579
+ }
12580
+ if (counts.warning > 0) {
12581
+ parts.push(`${counts.warning} warning${counts.warning !== 1 ? "s" : ""}`);
12582
+ }
12583
+ if (counts.info > 0) {
12584
+ parts.push(`${counts.info} info`);
12585
+ }
12586
+ const problemText = counts.total === 1 ? "problem" : "problems";
12587
+ return `
12588
+ ${x} ${counts.total} ${problemText} (${parts.join(", ")})
12589
+ `;
12590
+ }
12591
+ function formatHuman(results, filePath, options) {
12592
+ const color = options?.color ?? false;
12593
+ const failures = results.filter((r) => !r.passed);
12594
+ const lines = [];
12595
+ const header = color ? `${COLORS.bold}${filePath}${COLORS.reset}` : filePath;
12596
+ lines.push(header);
12597
+ for (const result of failures) {
12598
+ lines.push(formatFinding(result, color));
12599
+ }
12600
+ const counts = countSeverities(results);
12601
+ lines.push(formatSummary(counts, color));
12602
+ return lines.join("\n");
12603
+ }
12604
+ function formatMultiFileHuman(files, options) {
12605
+ const color = options?.color ?? false;
12606
+ const lines = [];
12607
+ const totalCounts = { error: 0, warning: 0, info: 0, total: 0 };
12608
+ for (const { file, results } of files) {
12609
+ const failures = results.filter((r) => !r.passed);
12610
+ if (failures.length === 0) continue;
12611
+ const header = color ? `${COLORS.bold}${file}${COLORS.reset}` : file;
12612
+ lines.push(header);
12613
+ for (const result of failures) {
12614
+ lines.push(formatFinding(result, color));
12615
+ }
12616
+ lines.push("");
12617
+ const counts = countSeverities(results);
12618
+ totalCounts.error += counts.error;
12619
+ totalCounts.warning += counts.warning;
12620
+ totalCounts.info += counts.info;
12621
+ totalCounts.total += counts.total;
12622
+ }
12623
+ lines.push(formatSummary(totalCounts, color));
12624
+ return lines.join("\n");
12625
+ }
12626
+
12530
12627
  // ../rules-default/src/common/network-rules.ts
12531
12628
  var NoMulticastBroadcastIp = {
12532
12629
  id: "NET-IP-001",
@@ -16510,7 +16607,7 @@ function enrichResultsWithRuleMetadata(results, rules) {
16510
16607
  });
16511
16608
  }
16512
16609
  var program = new Command();
16513
- program.name("sentriflow").description("SentriFlow Network Configuration Validator").version("0.4.2").argument("[files...]", "Path(s) to configuration file(s) (supports multiple files)").option("--ast", "Output the AST instead of rule results").option("-f, --format <format>", "Output format (json, sarif)", "json").option("-q, --quiet", "Only output failures (suppress passed results)").option("-c, --config <path>", "Path to config file (default: auto-detect)").option("--no-config", "Ignore config file").option("-r, --rules <path>", "Additional rules file to load (legacy)").option(
16610
+ program.name("sentriflow").description("SentriFlow Network Configuration Validator").version("0.5.0").argument("[files...]", "Path(s) to configuration file(s) (supports multiple files)").option("--ast", "Output the AST instead of rule results").option("-f, --format <format>", "Output format (json, human, sarif)", "json").option("-q, --quiet", "Only output failures (suppress passed results)").option("-c, --config <path>", "Path to config file (default: auto-detect)").option("--no-config", "Ignore config file").option("-r, --rules <path>", "Additional rules file to load (legacy)").option(
16514
16611
  "--pack <path...>",
16515
16612
  "Path(s) to rule pack(s) (.grx2 encrypted or unencrypted JS/TS modules)"
16516
16613
  ).option(
@@ -16937,6 +17034,13 @@ Parsing complete: ${allAsts.length} files`);
16937
17034
  console.log(
16938
17035
  generateMultiFileSarif(allFileResults, rules, sarifOptions)
16939
17036
  );
17037
+ } else if (options.format === "human") {
17038
+ const isColorEnabled = process.stdout.isTTY && !process.env.NO_COLOR;
17039
+ const humanFiles = allFileResults.map((fr) => ({
17040
+ file: fr.filePath,
17041
+ results: fr.results
17042
+ }));
17043
+ console.log(formatMultiFileHuman(humanFiles, { color: isColorEnabled }));
16940
17044
  } else {
16941
17045
  const output = {
16942
17046
  summary: {
@@ -17054,6 +17158,9 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
17054
17158
  baseDir: process.cwd()
17055
17159
  };
17056
17160
  console.log(generateSarif(results2, "<stdin>", stdinRules, sarifOptions, stdinIpSummary));
17161
+ } else if (options.format === "human") {
17162
+ const isColorEnabled = process.stdout.isTTY && !process.env.NO_COLOR;
17163
+ console.log(formatHuman(results2, "<stdin>", { color: isColorEnabled }));
17057
17164
  } else {
17058
17165
  const output = {
17059
17166
  file: "<stdin>",
@@ -17153,6 +17260,13 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
17153
17260
  console.log(
17154
17261
  generateMultiFileSarif(allFileResults, rules, sarifOptions)
17155
17262
  );
17263
+ } else if (options.format === "human") {
17264
+ const isColorEnabled = process.stdout.isTTY && !process.env.NO_COLOR;
17265
+ const humanFiles = allFileResults.map((fr) => ({
17266
+ file: fr.filePath,
17267
+ results: fr.results
17268
+ }));
17269
+ console.log(formatMultiFileHuman(humanFiles, { color: isColorEnabled }));
17156
17270
  } else {
17157
17271
  const output = {
17158
17272
  summary: {
@@ -17271,6 +17385,9 @@ Scan complete: ${allFileResults.length} files, ${totalFailures} failures, ${tota
17271
17385
  console.log(
17272
17386
  generateSarif(results, filePath, singleFileRules, sarifOptions, ipSummary)
17273
17387
  );
17388
+ } else if (options.format === "human") {
17389
+ const isColorEnabled = process.stdout.isTTY && !process.env.NO_COLOR;
17390
+ console.log(formatHuman(results, filePath, { color: isColorEnabled }));
17274
17391
  } else {
17275
17392
  const output = {
17276
17393
  vendor: {
@@ -17305,7 +17422,7 @@ async function loadLicensingExtension() {
17305
17422
  licensingModulePath
17306
17423
  );
17307
17424
  if (licensing.registerCommands) {
17308
- licensing.registerCommands(program, { cliVersion: "0.4.2" });
17425
+ licensing.registerCommands(program, { cliVersion: "0.5.0" });
17309
17426
  }
17310
17427
  } catch {
17311
17428
  const licensingMessage = `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentriflow/cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "SentriFlow CLI - Network configuration linter and validator",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",