@testchimp/cli 0.1.14 → 0.1.15

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.
@@ -634,39 +634,69 @@ export function buildCliProgram() {
634
634
  console.log(out);
635
635
  });
636
636
  program
637
- .command("run-sast-scan")
638
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "run-sast-scan").description)
637
+ .command("report-sast-findings")
638
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "report-sast-findings").description)
639
639
  .addOption(jsonInputOption())
640
- .option("--id <scanId>")
640
+ .option("--id <scanId>", "Security scan id")
641
+ .option("--report-file <path>", "Path to full Semgrep CLI JSON report")
641
642
  .action(async (opts) => {
642
643
  const body = {};
643
644
  if (opts.id)
644
645
  body.id = String(opts.id);
645
- const out = await runTool("run-sast-scan", mergeBodies(body, opts.jsonInput), { postMcp });
646
+ if (opts.reportFile)
647
+ body.reportFile = String(opts.reportFile);
648
+ const merged = mergeBodies(body, opts.jsonInput);
649
+ if (!merged.id || String(merged.id).trim() === "") {
650
+ throw new Error("id is required");
651
+ }
652
+ if (!merged.reportFile || String(merged.reportFile).trim() === "") {
653
+ throw new Error("reportFile is required (--report-file)");
654
+ }
655
+ const out = await runTool("report-sast-findings", { id: String(merged.id).trim(), reportFile: String(merged.reportFile).trim() }, { postMcp });
646
656
  console.log(out);
647
657
  });
648
658
  program
649
- .command("run-deps-scan")
650
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "run-deps-scan").description)
659
+ .command("report-secrets-findings")
660
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "report-secrets-findings").description)
651
661
  .addOption(jsonInputOption())
652
- .option("--id <scanId>")
662
+ .option("--id <scanId>", "Security scan id")
663
+ .option("--report-file <path>", "Path to full Gitleaks JSON report")
653
664
  .action(async (opts) => {
654
665
  const body = {};
655
666
  if (opts.id)
656
667
  body.id = String(opts.id);
657
- const out = await runTool("run-deps-scan", mergeBodies(body, opts.jsonInput), { postMcp });
668
+ if (opts.reportFile)
669
+ body.reportFile = String(opts.reportFile);
670
+ const merged = mergeBodies(body, opts.jsonInput);
671
+ if (!merged.id || String(merged.id).trim() === "") {
672
+ throw new Error("id is required");
673
+ }
674
+ if (!merged.reportFile || String(merged.reportFile).trim() === "") {
675
+ throw new Error("reportFile is required (--report-file)");
676
+ }
677
+ const out = await runTool("report-secrets-findings", { id: String(merged.id).trim(), reportFile: String(merged.reportFile).trim() }, { postMcp });
658
678
  console.log(out);
659
679
  });
660
680
  program
661
- .command("run-secrets-scan")
662
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "run-secrets-scan").description)
681
+ .command("report-deps-findings")
682
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "report-deps-findings").description)
663
683
  .addOption(jsonInputOption())
664
- .option("--id <scanId>")
684
+ .option("--id <scanId>", "Security scan id")
685
+ .option("--report-file <path>", "Path to full Trivy JSON report")
665
686
  .action(async (opts) => {
666
687
  const body = {};
667
688
  if (opts.id)
668
689
  body.id = String(opts.id);
669
- const out = await runTool("run-secrets-scan", mergeBodies(body, opts.jsonInput), { postMcp });
690
+ if (opts.reportFile)
691
+ body.reportFile = String(opts.reportFile);
692
+ const merged = mergeBodies(body, opts.jsonInput);
693
+ if (!merged.id || String(merged.id).trim() === "") {
694
+ throw new Error("id is required");
695
+ }
696
+ if (!merged.reportFile || String(merged.reportFile).trim() === "") {
697
+ throw new Error("reportFile is required (--report-file)");
698
+ }
699
+ const out = await runTool("report-deps-findings", { id: String(merged.id).trim(), reportFile: String(merged.reportFile).trim() }, { postMcp });
670
700
  console.log(out);
671
701
  });
672
702
  program
@@ -577,8 +577,17 @@ export declare const reportDastFindingsInput: z.ZodObject<{
577
577
  id: z.ZodString;
578
578
  reportFile: z.ZodString;
579
579
  }, z.core.$strip>;
580
- export declare const stubSecurityScanInput: z.ZodObject<{
581
- id: z.ZodOptional<z.ZodString>;
580
+ export declare const reportSastFindingsInput: z.ZodObject<{
581
+ id: z.ZodString;
582
+ reportFile: z.ZodString;
583
+ }, z.core.$strip>;
584
+ export declare const reportSecretsFindingsInput: z.ZodObject<{
585
+ id: z.ZodString;
586
+ reportFile: z.ZodString;
587
+ }, z.core.$strip>;
588
+ export declare const reportDepsFindingsInput: z.ZodObject<{
589
+ id: z.ZodString;
590
+ reportFile: z.ZodString;
582
591
  }, z.core.$strip>;
583
592
  /** UpsertScreenStatesRequest JSON (proto camelCase). */
584
593
  export declare const upsertScreenStatesInput: z.ZodObject<{
@@ -252,8 +252,20 @@ export const reportDastFindingsInput = z.object({
252
252
  /** Path to ZAP Traditional JSON report file */
253
253
  reportFile: z.string().min(1),
254
254
  });
255
- export const stubSecurityScanInput = z.object({
256
- id: z.string().min(1).optional(),
255
+ export const reportSastFindingsInput = z.object({
256
+ id: z.string().min(1),
257
+ /** Path to full Semgrep CLI JSON report file */
258
+ reportFile: z.string().min(1),
259
+ });
260
+ export const reportSecretsFindingsInput = z.object({
261
+ id: z.string().min(1),
262
+ /** Path to full Gitleaks JSON report file */
263
+ reportFile: z.string().min(1),
264
+ });
265
+ export const reportDepsFindingsInput = z.object({
266
+ id: z.string().min(1),
267
+ /** Path to full Trivy JSON report file */
268
+ reportFile: z.string().min(1),
257
269
  });
258
270
  const screenStatesEntrySchema = z.object({
259
271
  screen: z.string().optional(),
@@ -481,8 +481,10 @@ export const TOOL_DEFINITIONS = [
481
481
  },
482
482
  {
483
483
  kebab: "get-security-scan-config",
484
- description: "Fetch security scan config by scan id (categories, environment, release label, status). " +
485
- "Pass id (CLI: --id). Used by /testchimp run security scan.",
484
+ description: "Fetch security scan config by scan id (detail.dastCheckConfig / detail.sastCheckConfig / " +
485
+ "detail.depsCheckConfig / detail.leaksCheckConfig, release label, status). Pass id (CLI: --id). " +
486
+ "Used by /testchimp run security scan. For DAST honour allowActiveScan / useEphemeralSandbox / scope " +
487
+ "on dastCheckConfig.",
486
488
  inputSchema: S.getSecurityScanConfigInput,
487
489
  execute: async (args, { postMcp }) => {
488
490
  const a = args;
@@ -492,7 +494,8 @@ export const TOOL_DEFINITIONS = [
492
494
  {
493
495
  kebab: "update-scan-progress",
494
496
  description: "Update a scan's status. status must be one of: QUEUED, IN_PROGRESS, COMPLETED, EXCEPTION. " +
495
- "Call IN_PROGRESS when starting; COMPLETED when all selected categories finish; EXCEPTION on hard failure.",
497
+ "Call IN_PROGRESS when starting. Each scan is a single checker type: the category playbook " +
498
+ "sets COMPLETED after a successful report-*-findings (or EXCEPTION on hard failure).",
496
499
  inputSchema: S.updateScanProgressInput,
497
500
  execute: async (args, { postMcp }) => {
498
501
  const a = args;
@@ -506,7 +509,7 @@ export const TOOL_DEFINITIONS = [
506
509
  kebab: "report-dast-findings",
507
510
  description: "Upload a ZAP Traditional JSON report for a security scan. Pass --id and --report-file <path>. " +
508
511
  "Backend parses alerts, dedupes by bug hash, and inserts new SECURITY bugs linked to the scan. " +
509
- "Does not mark the scan COMPLETED.",
512
+ "Does not mark the scan COMPLETED — the DAST playbook calls update-scan-progress COMPLETED after this.",
510
513
  inputSchema: S.reportDastFindingsInput,
511
514
  execute: async (args, { postMcp }) => {
512
515
  const a = args;
@@ -519,22 +522,52 @@ export const TOOL_DEFINITIONS = [
519
522
  },
520
523
  },
521
524
  {
522
- kebab: "run-sast-scan",
523
- description: "Stub: Semgrep SAST scan is not implemented yet.",
524
- inputSchema: S.stubSecurityScanInput,
525
- execute: async () => JSON.stringify({ status: "not_implemented", tool: "run-sast-scan" }),
525
+ kebab: "report-sast-findings",
526
+ description: "Upload a full Semgrep CLI JSON report for a SAST security scan. Pass --id and --report-file <path>. " +
527
+ "Backend stores the raw report, parses results, dedupes by bug hash, and inserts new SECURITY bugs. " +
528
+ "Does not mark the scan COMPLETED the SAST playbook calls update-scan-progress COMPLETED after this.",
529
+ inputSchema: S.reportSastFindingsInput,
530
+ execute: async (args, { postMcp }) => {
531
+ const a = args;
532
+ const { readFile } = await import("node:fs/promises");
533
+ const reportJson = await readFile(a.reportFile, "utf8");
534
+ return postMcp("/api/mcp/report_sast_findings", {
535
+ scanId: a.id.trim(),
536
+ reportJson,
537
+ });
538
+ },
526
539
  },
527
540
  {
528
- kebab: "run-deps-scan",
529
- description: "Stub: Trivy dependency scan is not implemented yet.",
530
- inputSchema: S.stubSecurityScanInput,
531
- execute: async () => JSON.stringify({ status: "not_implemented", tool: "run-deps-scan" }),
541
+ kebab: "report-secrets-findings",
542
+ description: "Upload a full Gitleaks JSON report for a secrets security scan. Pass --id and --report-file <path>. " +
543
+ "Backend redacts secret payloads, stores the report, dedupes by bug hash, and inserts SECURITY bugs. " +
544
+ "Does not mark the scan COMPLETED the secrets playbook calls update-scan-progress COMPLETED after this.",
545
+ inputSchema: S.reportSecretsFindingsInput,
546
+ execute: async (args, { postMcp }) => {
547
+ const a = args;
548
+ const { readFile } = await import("node:fs/promises");
549
+ const reportJson = await readFile(a.reportFile, "utf8");
550
+ return postMcp("/api/mcp/report_secrets_findings", {
551
+ scanId: a.id.trim(),
552
+ reportJson,
553
+ });
554
+ },
532
555
  },
533
556
  {
534
- kebab: "run-secrets-scan",
535
- description: "Stub: Gitleaks secrets scan is not implemented yet.",
536
- inputSchema: S.stubSecurityScanInput,
537
- execute: async () => JSON.stringify({ status: "not_implemented", tool: "run-secrets-scan" }),
557
+ kebab: "report-deps-findings",
558
+ description: "Upload a full Trivy JSON report for a dependency security scan. Pass --id and --report-file <path>. " +
559
+ "Backend stores the report, filters by security profile / ignore-unfixed, dedupes, and inserts SECURITY bugs. " +
560
+ "Does not mark the scan COMPLETED the deps playbook calls update-scan-progress COMPLETED after this.",
561
+ inputSchema: S.reportDepsFindingsInput,
562
+ execute: async (args, { postMcp }) => {
563
+ const a = args;
564
+ const { readFile } = await import("node:fs/promises");
565
+ const reportJson = await readFile(a.reportFile, "utf8");
566
+ return postMcp("/api/mcp/report_deps_findings", {
567
+ scanId: a.id.trim(),
568
+ reportJson,
569
+ });
570
+ },
538
571
  },
539
572
  {
540
573
  kebab: "upsert-screen-states",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testchimp/cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "TestChimp CLI and MCP server — coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
5
5
  "type": "module",
6
6
  "main": "dist/bin/testchimp.js",