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