@fourteensystems/shipguard 0.1.0 → 0.2.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 (108) hide show
  1. package/README.md +42 -110
  2. package/dist/cli/commands/init.d.ts.map +1 -1
  3. package/dist/cli/commands/init.js +36 -0
  4. package/dist/cli/commands/init.js.map +1 -1
  5. package/dist/engine/baseline.test.d.ts +2 -0
  6. package/dist/engine/baseline.test.d.ts.map +1 -0
  7. package/dist/engine/baseline.test.js +135 -0
  8. package/dist/engine/baseline.test.js.map +1 -0
  9. package/dist/engine/config.d.ts.map +1 -1
  10. package/dist/engine/config.js +2 -0
  11. package/dist/engine/config.js.map +1 -1
  12. package/dist/engine/config.test.d.ts +2 -0
  13. package/dist/engine/config.test.d.ts.map +1 -0
  14. package/dist/engine/config.test.js +107 -0
  15. package/dist/engine/config.test.js.map +1 -0
  16. package/dist/engine/sarif.test.d.ts +2 -0
  17. package/dist/engine/sarif.test.d.ts.map +1 -0
  18. package/dist/engine/sarif.test.js +152 -0
  19. package/dist/engine/sarif.test.js.map +1 -0
  20. package/dist/engine/score.d.ts.map +1 -1
  21. package/dist/engine/score.js +13 -2
  22. package/dist/engine/score.js.map +1 -1
  23. package/dist/engine/score.test.d.ts +2 -0
  24. package/dist/engine/score.test.d.ts.map +1 -0
  25. package/dist/engine/score.test.js +191 -0
  26. package/dist/engine/score.test.js.map +1 -0
  27. package/dist/engine/types.d.ts +2 -0
  28. package/dist/engine/types.d.ts.map +1 -1
  29. package/dist/engine/waivers.test.d.ts +2 -0
  30. package/dist/engine/waivers.test.d.ts.map +1 -0
  31. package/dist/engine/waivers.test.js +147 -0
  32. package/dist/engine/waivers.test.js.map +1 -0
  33. package/dist/next/deps.d.ts.map +1 -1
  34. package/dist/next/deps.js +16 -0
  35. package/dist/next/deps.js.map +1 -1
  36. package/dist/next/deps.test.d.ts +2 -0
  37. package/dist/next/deps.test.d.ts.map +1 -0
  38. package/dist/next/deps.test.js +249 -0
  39. package/dist/next/deps.test.js.map +1 -0
  40. package/dist/next/detect.test.d.ts +2 -0
  41. package/dist/next/detect.test.d.ts.map +1 -0
  42. package/dist/next/detect.test.js +74 -0
  43. package/dist/next/detect.test.js.map +1 -0
  44. package/dist/next/index.d.ts.map +1 -1
  45. package/dist/next/index.js +11 -0
  46. package/dist/next/index.js.map +1 -1
  47. package/dist/next/middleware.d.ts.map +1 -1
  48. package/dist/next/middleware.js +15 -0
  49. package/dist/next/middleware.js.map +1 -1
  50. package/dist/next/middleware.test.d.ts +2 -0
  51. package/dist/next/middleware.test.d.ts.map +1 -0
  52. package/dist/next/middleware.test.js +203 -0
  53. package/dist/next/middleware.test.js.map +1 -0
  54. package/dist/next/routes.test.d.ts +2 -0
  55. package/dist/next/routes.test.d.ts.map +1 -0
  56. package/dist/next/routes.test.js +110 -0
  57. package/dist/next/routes.test.js.map +1 -0
  58. package/dist/next/server-actions.test.d.ts +2 -0
  59. package/dist/next/server-actions.test.d.ts.map +1 -0
  60. package/dist/next/server-actions.test.js +138 -0
  61. package/dist/next/server-actions.test.js.map +1 -0
  62. package/dist/next/trpc.d.ts.map +1 -1
  63. package/dist/next/trpc.js +4 -31
  64. package/dist/next/trpc.js.map +1 -1
  65. package/dist/next/types.d.ts +34 -0
  66. package/dist/next/types.d.ts.map +1 -1
  67. package/dist/next/wrappers.d.ts +10 -0
  68. package/dist/next/wrappers.d.ts.map +1 -0
  69. package/dist/next/wrappers.js +477 -0
  70. package/dist/next/wrappers.js.map +1 -0
  71. package/dist/next/wrappers.test.d.ts +2 -0
  72. package/dist/next/wrappers.test.d.ts.map +1 -0
  73. package/dist/next/wrappers.test.js +361 -0
  74. package/dist/next/wrappers.test.js.map +1 -0
  75. package/dist/rules/auth-boundary-missing.d.ts.map +1 -1
  76. package/dist/rules/auth-boundary-missing.js +23 -80
  77. package/dist/rules/auth-boundary-missing.js.map +1 -1
  78. package/dist/rules/index.d.ts.map +1 -1
  79. package/dist/rules/index.js +12 -0
  80. package/dist/rules/index.js.map +1 -1
  81. package/dist/rules/rate-limit-missing.d.ts.map +1 -1
  82. package/dist/rules/rate-limit-missing.js +34 -50
  83. package/dist/rules/rate-limit-missing.js.map +1 -1
  84. package/dist/rules/wrapper-unrecognized.d.ts +5 -0
  85. package/dist/rules/wrapper-unrecognized.d.ts.map +1 -0
  86. package/dist/rules/wrapper-unrecognized.js +76 -0
  87. package/dist/rules/wrapper-unrecognized.js.map +1 -0
  88. package/dist/util/hof.d.ts +22 -0
  89. package/dist/util/hof.d.ts.map +1 -0
  90. package/dist/util/hof.js +99 -0
  91. package/dist/util/hof.js.map +1 -0
  92. package/dist/util/hof.test.d.ts +2 -0
  93. package/dist/util/hof.test.d.ts.map +1 -0
  94. package/dist/util/hof.test.js +79 -0
  95. package/dist/util/hof.test.js.map +1 -0
  96. package/dist/util/monorepo.d.ts +6 -0
  97. package/dist/util/monorepo.d.ts.map +1 -0
  98. package/dist/util/monorepo.js +29 -0
  99. package/dist/util/monorepo.js.map +1 -0
  100. package/dist/util/resolve.d.ts +30 -0
  101. package/dist/util/resolve.d.ts.map +1 -0
  102. package/dist/util/resolve.js +306 -0
  103. package/dist/util/resolve.js.map +1 -0
  104. package/dist/util/resolve.test.d.ts +2 -0
  105. package/dist/util/resolve.test.d.ts.map +1 -0
  106. package/dist/util/resolve.test.js +186 -0
  107. package/dist/util/resolve.test.js.map +1 -0
  108. package/package.json +1 -1
@@ -0,0 +1,152 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { formatSarif } from "./sarif.js";
3
+ import { SHIPGUARD_VERSION } from "./version.js";
4
+ function makeFinding(overrides = {}) {
5
+ return {
6
+ ruleId: "AUTH-BOUNDARY-MISSING",
7
+ severity: "critical",
8
+ confidence: "high",
9
+ message: "No auth check found",
10
+ file: "app/api/users/route.ts",
11
+ line: 13,
12
+ evidence: ["no auth() call"],
13
+ confidenceRationale: "No auth function detected",
14
+ remediation: ["Add auth() check"],
15
+ tags: ["auth"],
16
+ ...overrides,
17
+ };
18
+ }
19
+ function makeScanResult(findings) {
20
+ return {
21
+ version: 1,
22
+ shipguardVersion: SHIPGUARD_VERSION,
23
+ configHash: "abc123",
24
+ indexVersion: 1,
25
+ timestamp: "2025-01-01T00:00:00.000Z",
26
+ framework: "next-app-router",
27
+ detected: {
28
+ deps: {
29
+ hasNextAuth: false, hasClerk: true, hasSupabase: false, hasKinde: false,
30
+ hasWorkOS: false, hasBetterAuth: false, hasLucia: false, hasAuth0: false,
31
+ hasIronSession: false, hasFirebaseAuth: false, hasUpstashRatelimit: false,
32
+ hasArcjet: false, hasUnkey: false, hasPrisma: true, hasDrizzle: false, hasTrpc: false,
33
+ },
34
+ trpc: false,
35
+ middleware: true,
36
+ },
37
+ score: 75,
38
+ findings,
39
+ waivedFindings: [],
40
+ summary: {
41
+ total: findings.length,
42
+ critical: findings.filter((f) => f.severity === "critical").length,
43
+ high: findings.filter((f) => f.severity === "high").length,
44
+ med: findings.filter((f) => f.severity === "med").length,
45
+ low: findings.filter((f) => f.severity === "low").length,
46
+ waived: 0,
47
+ },
48
+ };
49
+ }
50
+ describe("formatSarif", () => {
51
+ it("produces valid SARIF 2.1.0 structure", () => {
52
+ const result = makeScanResult([makeFinding()]);
53
+ const sarif = JSON.parse(formatSarif(result));
54
+ expect(sarif.$schema).toContain("sarif-schema-2.1.0");
55
+ expect(sarif.version).toBe("2.1.0");
56
+ expect(sarif.runs).toHaveLength(1);
57
+ });
58
+ it("includes tool driver info", () => {
59
+ const result = makeScanResult([makeFinding()]);
60
+ const sarif = JSON.parse(formatSarif(result));
61
+ const driver = sarif.runs[0].tool.driver;
62
+ expect(driver.name).toBe("Shipguard");
63
+ expect(driver.version).toBe(SHIPGUARD_VERSION);
64
+ });
65
+ it("maps findings to results", () => {
66
+ const findings = [
67
+ makeFinding({ ruleId: "AUTH-BOUNDARY-MISSING", file: "app/api/users/route.ts", line: 13 }),
68
+ makeFinding({ ruleId: "RATE-LIMIT-MISSING", severity: "high", file: "app/api/posts/route.ts", line: 5 }),
69
+ ];
70
+ const result = makeScanResult(findings);
71
+ const sarif = JSON.parse(formatSarif(result));
72
+ expect(sarif.runs[0].results).toHaveLength(2);
73
+ expect(sarif.runs[0].results[0].ruleId).toBe("AUTH-BOUNDARY-MISSING");
74
+ expect(sarif.runs[0].results[1].ruleId).toBe("RATE-LIMIT-MISSING");
75
+ });
76
+ it("deduplicates rules in driver", () => {
77
+ const findings = [
78
+ makeFinding({ ruleId: "AUTH-BOUNDARY-MISSING", file: "a.ts" }),
79
+ makeFinding({ ruleId: "AUTH-BOUNDARY-MISSING", file: "b.ts" }),
80
+ makeFinding({ ruleId: "RATE-LIMIT-MISSING", severity: "high", file: "c.ts" }),
81
+ ];
82
+ const result = makeScanResult(findings);
83
+ const sarif = JSON.parse(formatSarif(result));
84
+ expect(sarif.runs[0].tool.driver.rules).toHaveLength(2);
85
+ });
86
+ it("maps critical severity to error level", () => {
87
+ const result = makeScanResult([makeFinding({ severity: "critical" })]);
88
+ const sarif = JSON.parse(formatSarif(result));
89
+ expect(sarif.runs[0].results[0].level).toBe("error");
90
+ expect(sarif.runs[0].tool.driver.rules[0].defaultConfiguration.level).toBe("error");
91
+ });
92
+ it("maps high severity to warning level", () => {
93
+ const result = makeScanResult([makeFinding({ severity: "high" })]);
94
+ const sarif = JSON.parse(formatSarif(result));
95
+ expect(sarif.runs[0].results[0].level).toBe("warning");
96
+ });
97
+ it("maps med severity to note level", () => {
98
+ const result = makeScanResult([makeFinding({ severity: "med" })]);
99
+ const sarif = JSON.parse(formatSarif(result));
100
+ expect(sarif.runs[0].results[0].level).toBe("note");
101
+ });
102
+ it("maps low severity to note level", () => {
103
+ const result = makeScanResult([makeFinding({ severity: "low" })]);
104
+ const sarif = JSON.parse(formatSarif(result));
105
+ expect(sarif.runs[0].results[0].level).toBe("note");
106
+ });
107
+ it("includes physical location with line", () => {
108
+ const result = makeScanResult([makeFinding({ file: "app/api/test/route.ts", line: 42 })]);
109
+ const sarif = JSON.parse(formatSarif(result));
110
+ const loc = sarif.runs[0].results[0].locations[0].physicalLocation;
111
+ expect(loc.artifactLocation.uri).toBe("app/api/test/route.ts");
112
+ expect(loc.region.startLine).toBe(42);
113
+ });
114
+ it("includes column when present", () => {
115
+ const result = makeScanResult([makeFinding({ file: "a.ts", line: 10, column: 5 })]);
116
+ const sarif = JSON.parse(formatSarif(result));
117
+ const loc = sarif.runs[0].results[0].locations[0].physicalLocation;
118
+ expect(loc.region.startColumn).toBe(5);
119
+ });
120
+ it("omits region when no line", () => {
121
+ const result = makeScanResult([makeFinding({ file: "a.ts", line: undefined })]);
122
+ const sarif = JSON.parse(formatSarif(result));
123
+ const loc = sarif.runs[0].results[0].locations[0].physicalLocation;
124
+ expect(loc.region).toBeUndefined();
125
+ });
126
+ it("includes properties with confidence and evidence", () => {
127
+ const result = makeScanResult([makeFinding({ confidence: "high", evidence: ["no auth()"], remediation: ["add auth()"] })]);
128
+ const sarif = JSON.parse(formatSarif(result));
129
+ const props = sarif.runs[0].results[0].properties;
130
+ expect(props.confidence).toBe("high");
131
+ expect(props.evidence).toEqual(["no auth()"]);
132
+ expect(props.remediation).toEqual(["add auth()"]);
133
+ });
134
+ it("handles empty findings", () => {
135
+ const result = makeScanResult([]);
136
+ const sarif = JSON.parse(formatSarif(result));
137
+ expect(sarif.runs[0].results).toEqual([]);
138
+ expect(sarif.runs[0].tool.driver.rules).toEqual([]);
139
+ });
140
+ it("returns valid JSON string", () => {
141
+ const result = makeScanResult([makeFinding()]);
142
+ const output = formatSarif(result);
143
+ expect(() => JSON.parse(output)).not.toThrow();
144
+ });
145
+ it("formats with indentation", () => {
146
+ const result = makeScanResult([makeFinding()]);
147
+ const output = formatSarif(result);
148
+ expect(output).toContain("\n");
149
+ expect(output).toContain(" ");
150
+ });
151
+ });
152
+ //# sourceMappingURL=sarif.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.test.js","sourceRoot":"","sources":["../../src/engine/sarif.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/engine/score.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO7D,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,GAAE,aAA+B,GACtC,MAAM,CASR;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAM/E;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAGzD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAGrD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAQjD;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAqB9D"}
1
+ {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/engine/score.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO7D,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,GAAE,aAA+B,GACtC,MAAM,CAqBR;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAM/E;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAGzD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAGrD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAQjD;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAqB9D"}
@@ -4,9 +4,20 @@ const DEFAULT_SCORING = {
4
4
  };
5
5
  export function computeScore(findings, config = DEFAULT_SCORING) {
6
6
  let score = config.start;
7
+ const maxPerRule = config.maxPenaltyPerRule ?? config.start * 0.4;
8
+ // Group findings by ruleId
9
+ const byRule = new Map();
7
10
  for (const f of findings) {
8
- const penalty = config.penalties[f.severity] ?? 0;
9
- score -= penalty;
11
+ const list = byRule.get(f.ruleId) ?? [];
12
+ list.push(f);
13
+ byRule.set(f.ruleId, list);
14
+ }
15
+ for (const [, ruleFindings] of byRule) {
16
+ let ruleDeduction = 0;
17
+ for (const f of ruleFindings) {
18
+ ruleDeduction += config.penalties[f.severity] ?? 0;
19
+ }
20
+ score -= Math.min(ruleDeduction, maxPerRule);
10
21
  }
11
22
  return Math.max(0, score);
12
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/engine/score.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/engine/score.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=score.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.test.d.ts","sourceRoot":"","sources":["../../src/engine/score.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,191 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { computeScore, summarizeFindings, parseConfidence, parseSeverity, parseIntOrThrow, confidenceLevel, severityLevel, scoreStatus, buildDetectedList, } from "./score.js";
3
+ function makeFinding(overrides = {}) {
4
+ return {
5
+ ruleId: "TEST-RULE",
6
+ severity: "high",
7
+ confidence: "high",
8
+ message: "test finding",
9
+ file: "test.ts",
10
+ evidence: [],
11
+ confidenceRationale: "",
12
+ remediation: [],
13
+ tags: [],
14
+ ...overrides,
15
+ };
16
+ }
17
+ describe("computeScore", () => {
18
+ it("returns 100 with no findings", () => {
19
+ expect(computeScore([])).toBe(100);
20
+ });
21
+ it("subtracts penalty for each finding", () => {
22
+ const findings = [makeFinding({ severity: "critical" })];
23
+ expect(computeScore(findings)).toBe(75);
24
+ });
25
+ it("applies correct penalties per severity", () => {
26
+ expect(computeScore([makeFinding({ severity: "critical" })])).toBe(75);
27
+ expect(computeScore([makeFinding({ severity: "high" })])).toBe(90);
28
+ expect(computeScore([makeFinding({ severity: "med" })])).toBe(97);
29
+ expect(computeScore([makeFinding({ severity: "low" })])).toBe(99);
30
+ });
31
+ it("accumulates multiple findings from different rules", () => {
32
+ const findings = [
33
+ makeFinding({ ruleId: "RULE-A", severity: "critical" }),
34
+ makeFinding({ ruleId: "RULE-B", severity: "critical" }),
35
+ makeFinding({ ruleId: "RULE-C", severity: "high" }),
36
+ ];
37
+ expect(computeScore(findings)).toBe(40);
38
+ });
39
+ it("caps deduction per rule at 40% of start", () => {
40
+ // 10 critical findings from same rule = 250 raw penalty, capped at 40
41
+ const findings = Array.from({ length: 10 }, () => makeFinding({ severity: "critical" }));
42
+ expect(computeScore(findings)).toBe(60);
43
+ });
44
+ it("floors at 0 with enough different rules", () => {
45
+ const findings = [
46
+ makeFinding({ ruleId: "RULE-A", severity: "critical" }),
47
+ makeFinding({ ruleId: "RULE-A", severity: "critical" }),
48
+ makeFinding({ ruleId: "RULE-B", severity: "critical" }),
49
+ makeFinding({ ruleId: "RULE-B", severity: "critical" }),
50
+ makeFinding({ ruleId: "RULE-C", severity: "critical" }),
51
+ makeFinding({ ruleId: "RULE-C", severity: "critical" }),
52
+ ];
53
+ // Each rule: 50 raw, capped at 40. 3 rules * 40 = 120 > 100 → floors at 0
54
+ expect(computeScore(findings)).toBe(0);
55
+ });
56
+ it("uses custom scoring config", () => {
57
+ const config = { start: 50, penalties: { critical: 10, high: 5, med: 2, low: 1 } };
58
+ expect(computeScore([makeFinding({ severity: "critical" })], config)).toBe(40);
59
+ });
60
+ it("respects custom maxPenaltyPerRule", () => {
61
+ const config = {
62
+ start: 100,
63
+ penalties: { critical: 25, high: 10, med: 3, low: 1 },
64
+ maxPenaltyPerRule: 25,
65
+ };
66
+ // 5 critical from same rule = 125 raw, capped at 25
67
+ const findings = Array.from({ length: 5 }, () => makeFinding({ severity: "critical" }));
68
+ expect(computeScore(findings, config)).toBe(75);
69
+ });
70
+ it("applies cap independently per rule", () => {
71
+ // Two rules, each with findings that exceed the cap
72
+ const findings = [
73
+ makeFinding({ ruleId: "AUTH", severity: "critical" }),
74
+ makeFinding({ ruleId: "AUTH", severity: "critical" }),
75
+ makeFinding({ ruleId: "AUTH", severity: "critical" }),
76
+ makeFinding({ ruleId: "RATE", severity: "critical" }),
77
+ makeFinding({ ruleId: "RATE", severity: "critical" }),
78
+ makeFinding({ ruleId: "RATE", severity: "critical" }),
79
+ ];
80
+ // AUTH: 75 raw, capped at 40. RATE: 75 raw, capped at 40. Total: 80 → score 20
81
+ expect(computeScore(findings)).toBe(20);
82
+ });
83
+ });
84
+ describe("summarizeFindings", () => {
85
+ it("returns zero counts with no findings", () => {
86
+ expect(summarizeFindings([])).toEqual({ critical: 0, high: 0, med: 0, low: 0 });
87
+ });
88
+ it("counts by severity", () => {
89
+ const findings = [
90
+ makeFinding({ severity: "critical" }),
91
+ makeFinding({ severity: "critical" }),
92
+ makeFinding({ severity: "high" }),
93
+ makeFinding({ severity: "low" }),
94
+ ];
95
+ expect(summarizeFindings(findings)).toEqual({ critical: 2, high: 1, med: 0, low: 1 });
96
+ });
97
+ });
98
+ describe("parseConfidence", () => {
99
+ it("parses valid values", () => {
100
+ expect(parseConfidence("high")).toBe("high");
101
+ expect(parseConfidence("med")).toBe("med");
102
+ expect(parseConfidence("low")).toBe("low");
103
+ });
104
+ it("throws on invalid values", () => {
105
+ expect(() => parseConfidence("invalid")).toThrow("Invalid confidence");
106
+ expect(() => parseConfidence("")).toThrow("Invalid confidence");
107
+ });
108
+ });
109
+ describe("parseSeverity", () => {
110
+ it("parses valid values", () => {
111
+ expect(parseSeverity("critical")).toBe("critical");
112
+ expect(parseSeverity("high")).toBe("high");
113
+ expect(parseSeverity("med")).toBe("med");
114
+ expect(parseSeverity("low")).toBe("low");
115
+ });
116
+ it("throws on invalid values", () => {
117
+ expect(() => parseSeverity("medium")).toThrow("Invalid severity");
118
+ expect(() => parseSeverity("")).toThrow("Invalid severity");
119
+ });
120
+ });
121
+ describe("parseIntOrThrow", () => {
122
+ it("parses valid integers", () => {
123
+ expect(parseIntOrThrow("42", "test")).toBe(42);
124
+ expect(parseIntOrThrow("0", "test")).toBe(0);
125
+ expect(parseIntOrThrow("-1", "test")).toBe(-1);
126
+ });
127
+ it("throws on non-numbers", () => {
128
+ expect(() => parseIntOrThrow("abc", "test")).toThrow("Invalid test");
129
+ expect(() => parseIntOrThrow("", "test")).toThrow("Invalid test");
130
+ });
131
+ });
132
+ describe("confidenceLevel", () => {
133
+ it("maps confidence to numeric level", () => {
134
+ expect(confidenceLevel("high")).toBe(3);
135
+ expect(confidenceLevel("med")).toBe(2);
136
+ expect(confidenceLevel("low")).toBe(1);
137
+ });
138
+ });
139
+ describe("severityLevel", () => {
140
+ it("maps severity to numeric level", () => {
141
+ expect(severityLevel("critical")).toBe(4);
142
+ expect(severityLevel("high")).toBe(3);
143
+ expect(severityLevel("med")).toBe(2);
144
+ expect(severityLevel("low")).toBe(1);
145
+ });
146
+ });
147
+ describe("scoreStatus", () => {
148
+ it("returns PASS for scores >= 80", () => {
149
+ expect(scoreStatus(100)).toBe("PASS");
150
+ expect(scoreStatus(80)).toBe("PASS");
151
+ });
152
+ it("returns WARN for scores 50-79", () => {
153
+ expect(scoreStatus(79)).toBe("WARN");
154
+ expect(scoreStatus(50)).toBe("WARN");
155
+ });
156
+ it("returns FAIL for scores < 50", () => {
157
+ expect(scoreStatus(49)).toBe("FAIL");
158
+ expect(scoreStatus(0)).toBe("FAIL");
159
+ });
160
+ });
161
+ describe("buildDetectedList", () => {
162
+ function makeEmptyDeps() {
163
+ return {
164
+ hasNextAuth: false, hasClerk: false, hasSupabase: false,
165
+ hasKinde: false, hasWorkOS: false, hasBetterAuth: false,
166
+ hasLucia: false, hasAuth0: false, hasIronSession: false,
167
+ hasFirebaseAuth: false, hasPrisma: false, hasDrizzle: false,
168
+ hasTrpc: false, hasUpstashRatelimit: false, hasArcjet: false,
169
+ hasUnkey: false,
170
+ };
171
+ }
172
+ it("always includes next-app-router", () => {
173
+ const result = {
174
+ detected: { deps: makeEmptyDeps(), trpc: false, middleware: false },
175
+ };
176
+ expect(buildDetectedList(result)).toEqual(["next-app-router"]);
177
+ });
178
+ it("includes detected deps", () => {
179
+ const deps = makeEmptyDeps();
180
+ deps.hasClerk = true;
181
+ deps.hasPrisma = true;
182
+ const result = {
183
+ detected: { deps, trpc: false, middleware: true },
184
+ };
185
+ const list = buildDetectedList(result);
186
+ expect(list).toContain("clerk");
187
+ expect(list).toContain("prisma");
188
+ expect(list).toContain("middleware");
189
+ });
190
+ });
191
+ //# sourceMappingURL=score.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.test.js","sourceRoot":"","sources":["../../src/engine/score.test.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,8 @@ export interface ScanResult {
62
62
  export interface ScoringConfig {
63
63
  start: number;
64
64
  penalties: Record<Severity, number>;
65
+ /** Max deduction any single rule can impose. Defaults to start * 0.4 */
66
+ maxPenaltyPerRule?: number;
65
67
  }
66
68
  export interface ShipguardConfig {
67
69
  framework: "next-app-router";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=waivers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waivers.test.d.ts","sourceRoot":"","sources":["../../src/engine/waivers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,147 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, rmSync, writeFileSync, readFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { loadWaivers, saveWaivers, addWaiver, applyWaivers } from "./waivers.js";
6
+ function makeFinding(overrides = {}) {
7
+ return {
8
+ ruleId: "TEST-RULE",
9
+ severity: "high",
10
+ confidence: "high",
11
+ message: "test",
12
+ file: "test.ts",
13
+ evidence: [],
14
+ confidenceRationale: "",
15
+ remediation: [],
16
+ tags: [],
17
+ ...overrides,
18
+ };
19
+ }
20
+ describe("loadWaivers", () => {
21
+ let tmpDir;
22
+ beforeEach(() => {
23
+ tmpDir = mkdtempSync(path.join(os.tmpdir(), "shipguard-waivers-"));
24
+ });
25
+ afterEach(() => {
26
+ rmSync(tmpDir, { recursive: true, force: true });
27
+ });
28
+ it("returns empty array when file does not exist", () => {
29
+ expect(loadWaivers(tmpDir, "waivers.json")).toEqual([]);
30
+ });
31
+ it("loads legacy array format", () => {
32
+ const waivers = [{ ruleId: "R1", file: "a.ts", reason: "ok", createdAt: "2024-01-01" }];
33
+ writeFileSync(path.join(tmpDir, "waivers.json"), JSON.stringify(waivers));
34
+ expect(loadWaivers(tmpDir, "waivers.json")).toEqual(waivers);
35
+ });
36
+ it("loads versioned format", () => {
37
+ const file = { version: 1, waivers: [{ ruleId: "R1", file: "a.ts", reason: "ok", createdAt: "2024-01-01" }] };
38
+ writeFileSync(path.join(tmpDir, "waivers.json"), JSON.stringify(file));
39
+ expect(loadWaivers(tmpDir, "waivers.json")).toHaveLength(1);
40
+ });
41
+ it("throws on malformed JSON", () => {
42
+ writeFileSync(path.join(tmpDir, "waivers.json"), "not json");
43
+ expect(() => loadWaivers(tmpDir, "waivers.json")).toThrow("Failed to parse");
44
+ });
45
+ });
46
+ describe("saveWaivers / addWaiver", () => {
47
+ let tmpDir;
48
+ beforeEach(() => {
49
+ tmpDir = mkdtempSync(path.join(os.tmpdir(), "shipguard-waivers-"));
50
+ });
51
+ afterEach(() => {
52
+ rmSync(tmpDir, { recursive: true, force: true });
53
+ });
54
+ it("saves and loads roundtrip", () => {
55
+ const waivers = [{ ruleId: "R1", file: "a.ts", reason: "ok", createdAt: "2024-01-01" }];
56
+ saveWaivers(tmpDir, "w.json", waivers);
57
+ const loaded = loadWaivers(tmpDir, "w.json");
58
+ expect(loaded).toEqual(waivers);
59
+ });
60
+ it("saves in versioned format", () => {
61
+ saveWaivers(tmpDir, "w.json", []);
62
+ const raw = JSON.parse(readFileSync(path.join(tmpDir, "w.json"), "utf8"));
63
+ expect(raw.version).toBe(1);
64
+ expect(raw.waivers).toEqual([]);
65
+ });
66
+ it("addWaiver appends and sets createdAt", () => {
67
+ const waiver = addWaiver(tmpDir, "w.json", { ruleId: "R1", file: "a.ts", reason: "test" });
68
+ expect(waiver.createdAt).toBeDefined();
69
+ expect(waiver.ruleId).toBe("R1");
70
+ const loaded = loadWaivers(tmpDir, "w.json");
71
+ expect(loaded).toHaveLength(1);
72
+ });
73
+ it("addWaiver accumulates waivers", () => {
74
+ addWaiver(tmpDir, "w.json", { ruleId: "R1", file: "a.ts", reason: "first" });
75
+ addWaiver(tmpDir, "w.json", { ruleId: "R2", file: "b.ts", reason: "second" });
76
+ const loaded = loadWaivers(tmpDir, "w.json");
77
+ expect(loaded).toHaveLength(2);
78
+ });
79
+ });
80
+ describe("applyWaivers", () => {
81
+ it("returns all findings as active when no waivers", () => {
82
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
83
+ const { active, waived } = applyWaivers(findings, []);
84
+ expect(active).toHaveLength(1);
85
+ expect(waived).toHaveLength(0);
86
+ });
87
+ it("waives matching findings", () => {
88
+ const findings = [
89
+ makeFinding({ ruleId: "R1", file: "a.ts" }),
90
+ makeFinding({ ruleId: "R2", file: "b.ts" }),
91
+ ];
92
+ const waivers = [
93
+ { ruleId: "R1", file: "a.ts", reason: "ok", createdAt: "2024-01-01" },
94
+ ];
95
+ const { active, waived } = applyWaivers(findings, waivers);
96
+ expect(active).toHaveLength(1);
97
+ expect(active[0].ruleId).toBe("R2");
98
+ expect(waived).toHaveLength(1);
99
+ expect(waived[0].ruleId).toBe("R1");
100
+ });
101
+ it("does not waive when ruleId differs", () => {
102
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
103
+ const waivers = [
104
+ { ruleId: "R2", file: "a.ts", reason: "ok", createdAt: "2024-01-01" },
105
+ ];
106
+ const { active, waived } = applyWaivers(findings, waivers);
107
+ expect(active).toHaveLength(1);
108
+ expect(waived).toHaveLength(0);
109
+ });
110
+ it("does not waive when file differs", () => {
111
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
112
+ const waivers = [
113
+ { ruleId: "R1", file: "b.ts", reason: "ok", createdAt: "2024-01-01" },
114
+ ];
115
+ const { active, waived } = applyWaivers(findings, waivers);
116
+ expect(active).toHaveLength(1);
117
+ expect(waived).toHaveLength(0);
118
+ });
119
+ it("ignores expired waivers", () => {
120
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
121
+ const waivers = [
122
+ { ruleId: "R1", file: "a.ts", reason: "ok", expiry: "2020-01-01", createdAt: "2019-01-01" },
123
+ ];
124
+ const { active, waived } = applyWaivers(findings, waivers);
125
+ expect(active).toHaveLength(1);
126
+ expect(waived).toHaveLength(0);
127
+ });
128
+ it("applies non-expired waivers", () => {
129
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
130
+ const waivers = [
131
+ { ruleId: "R1", file: "a.ts", reason: "ok", expiry: "2099-01-01", createdAt: "2024-01-01" },
132
+ ];
133
+ const { active, waived } = applyWaivers(findings, waivers);
134
+ expect(active).toHaveLength(0);
135
+ expect(waived).toHaveLength(1);
136
+ });
137
+ it("applies waivers without expiry", () => {
138
+ const findings = [makeFinding({ ruleId: "R1", file: "a.ts" })];
139
+ const waivers = [
140
+ { ruleId: "R1", file: "a.ts", reason: "ok", createdAt: "2024-01-01" },
141
+ ];
142
+ const { active, waived } = applyWaivers(findings, waivers);
143
+ expect(active).toHaveLength(0);
144
+ expect(waived).toHaveLength(1);
145
+ });
146
+ });
147
+ //# sourceMappingURL=waivers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waivers.test.js","sourceRoot":"","sources":["../../src/engine/waivers.test.ts"],"names":[],"mappings":"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"}