vaspera 2.10.0 → 2.11.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 (206) hide show
  1. package/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts +2 -0
  2. package/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts.map +1 -0
  3. package/dist/__tests__/scanners/ai-code/ai-detector.test.js +188 -0
  4. package/dist/__tests__/scanners/ai-code/ai-detector.test.js.map +1 -0
  5. package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts +2 -0
  6. package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts.map +1 -0
  7. package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js +363 -0
  8. package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js.map +1 -0
  9. package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts +2 -0
  10. package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts.map +1 -0
  11. package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js +226 -0
  12. package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js.map +1 -0
  13. package/dist/__tests__/scanners/ai-code/index.test.d.ts +2 -0
  14. package/dist/__tests__/scanners/ai-code/index.test.d.ts.map +1 -0
  15. package/dist/__tests__/scanners/ai-code/index.test.js +214 -0
  16. package/dist/__tests__/scanners/ai-code/index.test.js.map +1 -0
  17. package/dist/__tests__/scanners/deploy/health-checker.test.d.ts +2 -0
  18. package/dist/__tests__/scanners/deploy/health-checker.test.d.ts.map +1 -0
  19. package/dist/__tests__/scanners/deploy/health-checker.test.js +67 -0
  20. package/dist/__tests__/scanners/deploy/health-checker.test.js.map +1 -0
  21. package/dist/__tests__/scanners/deploy/index.test.d.ts +2 -0
  22. package/dist/__tests__/scanners/deploy/index.test.d.ts.map +1 -0
  23. package/dist/__tests__/scanners/deploy/index.test.js +84 -0
  24. package/dist/__tests__/scanners/deploy/index.test.js.map +1 -0
  25. package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts +2 -0
  26. package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts.map +1 -0
  27. package/dist/__tests__/scanners/deploy/provider-detector.test.js +88 -0
  28. package/dist/__tests__/scanners/deploy/provider-detector.test.js.map +1 -0
  29. package/dist/__tests__/scanners/deploy/types.test.d.ts +2 -0
  30. package/dist/__tests__/scanners/deploy/types.test.d.ts.map +1 -0
  31. package/dist/__tests__/scanners/deploy/types.test.js +126 -0
  32. package/dist/__tests__/scanners/deploy/types.test.js.map +1 -0
  33. package/dist/__tests__/scanners/fp-feedback.test.js +1 -1
  34. package/dist/__tests__/scanners/fp-feedback.test.js.map +1 -1
  35. package/dist/__tests__/scanners/fp-tracker.test.js +1 -1
  36. package/dist/__tests__/scanners/fp-tracker.test.js.map +1 -1
  37. package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts +2 -0
  38. package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts.map +1 -0
  39. package/dist/__tests__/scanners/runtime/app-launcher.test.js +94 -0
  40. package/dist/__tests__/scanners/runtime/app-launcher.test.js.map +1 -0
  41. package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts +2 -0
  42. package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts.map +1 -0
  43. package/dist/__tests__/scanners/runtime/golden-path-runner.test.js +195 -0
  44. package/dist/__tests__/scanners/runtime/golden-path-runner.test.js.map +1 -0
  45. package/dist/__tests__/scanners/runtime/index.test.d.ts +2 -0
  46. package/dist/__tests__/scanners/runtime/index.test.d.ts.map +1 -0
  47. package/dist/__tests__/scanners/runtime/index.test.js +120 -0
  48. package/dist/__tests__/scanners/runtime/index.test.js.map +1 -0
  49. package/dist/__tests__/scanners/runtime/types.test.d.ts +2 -0
  50. package/dist/__tests__/scanners/runtime/types.test.d.ts.map +1 -0
  51. package/dist/__tests__/scanners/runtime/types.test.js +126 -0
  52. package/dist/__tests__/scanners/runtime/types.test.js.map +1 -0
  53. package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts +2 -0
  54. package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts.map +1 -0
  55. package/dist/__tests__/scanners/scale/bottleneck-detector.test.js +187 -0
  56. package/dist/__tests__/scanners/scale/bottleneck-detector.test.js.map +1 -0
  57. package/dist/__tests__/scanners/scale/index.test.d.ts +2 -0
  58. package/dist/__tests__/scanners/scale/index.test.d.ts.map +1 -0
  59. package/dist/__tests__/scanners/scale/index.test.js +87 -0
  60. package/dist/__tests__/scanners/scale/index.test.js.map +1 -0
  61. package/dist/__tests__/scanners/scale/load-profiler.test.d.ts +2 -0
  62. package/dist/__tests__/scanners/scale/load-profiler.test.d.ts.map +1 -0
  63. package/dist/__tests__/scanners/scale/load-profiler.test.js +122 -0
  64. package/dist/__tests__/scanners/scale/load-profiler.test.js.map +1 -0
  65. package/dist/__tests__/scanners/scale/types.test.d.ts +2 -0
  66. package/dist/__tests__/scanners/scale/types.test.d.ts.map +1 -0
  67. package/dist/__tests__/scanners/scale/types.test.js +129 -0
  68. package/dist/__tests__/scanners/scale/types.test.js.map +1 -0
  69. package/dist/action/pr-comment.test.js +8 -0
  70. package/dist/action/pr-comment.test.js.map +1 -1
  71. package/dist/action/sarif-upload.test.js +8 -0
  72. package/dist/action/sarif-upload.test.js.map +1 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +874 -0
  75. package/dist/index.js.map +1 -1
  76. package/dist/install-skills.d.ts +11 -0
  77. package/dist/install-skills.d.ts.map +1 -0
  78. package/dist/install-skills.js +81 -0
  79. package/dist/install-skills.js.map +1 -0
  80. package/dist/scanners/ai-code/ai-detector.d.ts +25 -0
  81. package/dist/scanners/ai-code/ai-detector.d.ts.map +1 -0
  82. package/dist/scanners/ai-code/ai-detector.js +192 -0
  83. package/dist/scanners/ai-code/ai-detector.js.map +1 -0
  84. package/dist/scanners/ai-code/confidence-scorer.d.ts +40 -0
  85. package/dist/scanners/ai-code/confidence-scorer.d.ts.map +1 -0
  86. package/dist/scanners/ai-code/confidence-scorer.js +148 -0
  87. package/dist/scanners/ai-code/confidence-scorer.js.map +1 -0
  88. package/dist/scanners/ai-code/hallucination-checker.d.ts +36 -0
  89. package/dist/scanners/ai-code/hallucination-checker.d.ts.map +1 -0
  90. package/dist/scanners/ai-code/hallucination-checker.js +298 -0
  91. package/dist/scanners/ai-code/hallucination-checker.js.map +1 -0
  92. package/dist/scanners/ai-code/index.d.ts +30 -0
  93. package/dist/scanners/ai-code/index.d.ts.map +1 -0
  94. package/dist/scanners/ai-code/index.js +224 -0
  95. package/dist/scanners/ai-code/index.js.map +1 -0
  96. package/dist/scanners/ai-code/types.d.ts +192 -0
  97. package/dist/scanners/ai-code/types.d.ts.map +1 -0
  98. package/dist/scanners/ai-code/types.js +37 -0
  99. package/dist/scanners/ai-code/types.js.map +1 -0
  100. package/dist/scanners/cache.d.ts.map +1 -1
  101. package/dist/scanners/cache.js +8 -0
  102. package/dist/scanners/cache.js.map +1 -1
  103. package/dist/scanners/dast.d.ts +40 -0
  104. package/dist/scanners/dast.d.ts.map +1 -0
  105. package/dist/scanners/dast.js +228 -0
  106. package/dist/scanners/dast.js.map +1 -0
  107. package/dist/scanners/deploy/health-checker.d.ts +38 -0
  108. package/dist/scanners/deploy/health-checker.d.ts.map +1 -0
  109. package/dist/scanners/deploy/health-checker.js +272 -0
  110. package/dist/scanners/deploy/health-checker.js.map +1 -0
  111. package/dist/scanners/deploy/index.d.ts +44 -0
  112. package/dist/scanners/deploy/index.d.ts.map +1 -0
  113. package/dist/scanners/deploy/index.js +208 -0
  114. package/dist/scanners/deploy/index.js.map +1 -0
  115. package/dist/scanners/deploy/provider-detector.d.ts +25 -0
  116. package/dist/scanners/deploy/provider-detector.d.ts.map +1 -0
  117. package/dist/scanners/deploy/provider-detector.js +177 -0
  118. package/dist/scanners/deploy/provider-detector.js.map +1 -0
  119. package/dist/scanners/deploy/types.d.ts +406 -0
  120. package/dist/scanners/deploy/types.d.ts.map +1 -0
  121. package/dist/scanners/deploy/types.js +58 -0
  122. package/dist/scanners/deploy/types.js.map +1 -0
  123. package/dist/scanners/deploy/vercel-integration.d.ts +52 -0
  124. package/dist/scanners/deploy/vercel-integration.d.ts.map +1 -0
  125. package/dist/scanners/deploy/vercel-integration.js +280 -0
  126. package/dist/scanners/deploy/vercel-integration.js.map +1 -0
  127. package/dist/scanners/index.d.ts +4 -4
  128. package/dist/scanners/index.d.ts.map +1 -1
  129. package/dist/scanners/index.js +133 -15
  130. package/dist/scanners/index.js.map +1 -1
  131. package/dist/scanners/index.test.js +6 -6
  132. package/dist/scanners/index.test.js.map +1 -1
  133. package/dist/scanners/openapi.d.ts +20 -0
  134. package/dist/scanners/openapi.d.ts.map +1 -0
  135. package/dist/scanners/openapi.js +226 -0
  136. package/dist/scanners/openapi.js.map +1 -0
  137. package/dist/scanners/runtime/app-launcher.d.ts +33 -0
  138. package/dist/scanners/runtime/app-launcher.d.ts.map +1 -0
  139. package/dist/scanners/runtime/app-launcher.js +419 -0
  140. package/dist/scanners/runtime/app-launcher.js.map +1 -0
  141. package/dist/scanners/runtime/golden-path-runner.d.ts +48 -0
  142. package/dist/scanners/runtime/golden-path-runner.d.ts.map +1 -0
  143. package/dist/scanners/runtime/golden-path-runner.js +373 -0
  144. package/dist/scanners/runtime/golden-path-runner.js.map +1 -0
  145. package/dist/scanners/runtime/index.d.ts +41 -0
  146. package/dist/scanners/runtime/index.d.ts.map +1 -0
  147. package/dist/scanners/runtime/index.js +164 -0
  148. package/dist/scanners/runtime/index.js.map +1 -0
  149. package/dist/scanners/runtime/playwright-executor.d.ts +50 -0
  150. package/dist/scanners/runtime/playwright-executor.d.ts.map +1 -0
  151. package/dist/scanners/runtime/playwright-executor.js +387 -0
  152. package/dist/scanners/runtime/playwright-executor.js.map +1 -0
  153. package/dist/scanners/runtime/types.d.ts +215 -0
  154. package/dist/scanners/runtime/types.d.ts.map +1 -0
  155. package/dist/scanners/runtime/types.js +40 -0
  156. package/dist/scanners/runtime/types.js.map +1 -0
  157. package/dist/scanners/rust.d.ts +22 -0
  158. package/dist/scanners/rust.d.ts.map +1 -0
  159. package/dist/scanners/rust.js +239 -0
  160. package/dist/scanners/rust.js.map +1 -0
  161. package/dist/scanners/scale/bottleneck-detector.d.ts +17 -0
  162. package/dist/scanners/scale/bottleneck-detector.d.ts.map +1 -0
  163. package/dist/scanners/scale/bottleneck-detector.js +250 -0
  164. package/dist/scanners/scale/bottleneck-detector.js.map +1 -0
  165. package/dist/scanners/scale/capacity-estimator.d.ts +17 -0
  166. package/dist/scanners/scale/capacity-estimator.d.ts.map +1 -0
  167. package/dist/scanners/scale/capacity-estimator.js +197 -0
  168. package/dist/scanners/scale/capacity-estimator.js.map +1 -0
  169. package/dist/scanners/scale/index.d.ts +37 -0
  170. package/dist/scanners/scale/index.d.ts.map +1 -0
  171. package/dist/scanners/scale/index.js +101 -0
  172. package/dist/scanners/scale/index.js.map +1 -0
  173. package/dist/scanners/scale/load-profiler.d.ts +48 -0
  174. package/dist/scanners/scale/load-profiler.d.ts.map +1 -0
  175. package/dist/scanners/scale/load-profiler.js +377 -0
  176. package/dist/scanners/scale/load-profiler.js.map +1 -0
  177. package/dist/scanners/scale/types.d.ts +529 -0
  178. package/dist/scanners/scale/types.d.ts.map +1 -0
  179. package/dist/scanners/scale/types.js +57 -0
  180. package/dist/scanners/scale/types.js.map +1 -0
  181. package/dist/scanners/secrets.d.ts.map +1 -1
  182. package/dist/scanners/secrets.js +13 -2
  183. package/dist/scanners/secrets.js.map +1 -1
  184. package/dist/scanners/terraform.d.ts +23 -0
  185. package/dist/scanners/terraform.d.ts.map +1 -0
  186. package/dist/scanners/terraform.js +207 -0
  187. package/dist/scanners/terraform.js.map +1 -0
  188. package/dist/scanners/types.d.ts +1 -1
  189. package/dist/scanners/types.d.ts.map +1 -1
  190. package/dist/scanners/types.js +8 -0
  191. package/dist/scanners/types.js.map +1 -1
  192. package/package.json +4 -2
  193. package/skills/vaspera-add-tests/SKILL.md +102 -0
  194. package/skills/vaspera-ai-verify/SKILL.md +166 -0
  195. package/skills/vaspera-audit/SKILL.md +67 -0
  196. package/skills/vaspera-certify/SKILL.md +130 -0
  197. package/skills/vaspera-deploy/SKILL.md +152 -0
  198. package/skills/vaspera-fix-critical/SKILL.md +52 -0
  199. package/skills/vaspera-fix-high/SKILL.md +81 -0
  200. package/skills/vaspera-fix-medium/SKILL.md +56 -0
  201. package/skills/vaspera-fix-rls/SKILL.md +85 -0
  202. package/skills/vaspera-harden/SKILL.md +102 -0
  203. package/skills/vaspera-help/SKILL.md +61 -0
  204. package/skills/vaspera-load-test/SKILL.md +167 -0
  205. package/skills/vaspera-verify/SKILL.md +70 -0
  206. package/skills/vaspera-verify-e2e/SKILL.md +117 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Rust Security Scanner
3
+ *
4
+ * Scans Rust projects for security vulnerabilities using
5
+ * cargo-audit and clippy.
6
+ *
7
+ * @module scanners/rust
8
+ */
9
+ import type { ScannerResult, ScannerAvailability } from "./types.js";
10
+ export declare function checkCargoAuditAvailable(): Promise<ScannerAvailability>;
11
+ export declare function checkClippyAvailable(): Promise<ScannerAvailability>;
12
+ export declare function runCargoAudit(projectPath: string, options?: {
13
+ timeout?: number;
14
+ }): Promise<ScannerResult>;
15
+ export declare function runClippy(projectPath: string, options?: {
16
+ timeout?: number;
17
+ }): Promise<ScannerResult>;
18
+ export declare function runRustScanners(projectPath: string, options?: {
19
+ timeout?: number;
20
+ }): Promise<ScannerResult>;
21
+ export declare function detectRust(projectPath: string): Promise<boolean>;
22
+ //# sourceMappingURL=rust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust.d.ts","sourceRoot":"","sources":["../../src/scanners/rust.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAwB,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAmE3F,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAe7E;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAezE;AAgBD,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAqFxB;AAED,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAmFxB;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAkBxB;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOtE"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Rust Security Scanner
3
+ *
4
+ * Scans Rust projects for security vulnerabilities using
5
+ * cargo-audit and clippy.
6
+ *
7
+ * @module scanners/rust
8
+ */
9
+ import { exec } from "child_process";
10
+ import { promisify } from "util";
11
+ import { access } from "fs/promises";
12
+ import { join } from "path";
13
+ const execAsync = promisify(exec);
14
+ export async function checkCargoAuditAvailable() {
15
+ try {
16
+ const { stdout } = await execAsync("cargo audit --version", { timeout: 10000 });
17
+ return {
18
+ scanner: "cargo-audit",
19
+ available: true,
20
+ version: stdout.trim(),
21
+ };
22
+ }
23
+ catch {
24
+ return {
25
+ scanner: "cargo-audit",
26
+ available: false,
27
+ error: "cargo-audit not found. Install with: cargo install cargo-audit",
28
+ };
29
+ }
30
+ }
31
+ export async function checkClippyAvailable() {
32
+ try {
33
+ const { stdout } = await execAsync("cargo clippy --version", { timeout: 10000 });
34
+ return {
35
+ scanner: "clippy",
36
+ available: true,
37
+ version: stdout.trim(),
38
+ };
39
+ }
40
+ catch {
41
+ return {
42
+ scanner: "clippy",
43
+ available: false,
44
+ error: "clippy not found. Install with: rustup component add clippy",
45
+ };
46
+ }
47
+ }
48
+ function mapAuditSeverity(severity) {
49
+ switch (severity.toLowerCase()) {
50
+ case "critical":
51
+ return "critical";
52
+ case "high":
53
+ return "high";
54
+ case "medium":
55
+ case "moderate":
56
+ return "medium";
57
+ default:
58
+ return "low";
59
+ }
60
+ }
61
+ export async function runCargoAudit(projectPath, options) {
62
+ const startTime = Date.now();
63
+ try {
64
+ const availability = await checkCargoAuditAvailable();
65
+ if (!availability.available) {
66
+ return {
67
+ scanner: "cargo-audit",
68
+ findings: [],
69
+ duration: Date.now() - startTime,
70
+ success: false,
71
+ error: availability.error,
72
+ };
73
+ }
74
+ const { stdout } = await execAsync(`cd "${projectPath}" && cargo audit --json`, {
75
+ timeout: options?.timeout || 120000,
76
+ maxBuffer: 10 * 1024 * 1024,
77
+ }).catch((error) => {
78
+ if (error.stdout) {
79
+ return { stdout: error.stdout, stderr: error.stderr || "" };
80
+ }
81
+ throw error;
82
+ });
83
+ const output = JSON.parse(stdout);
84
+ const findings = [];
85
+ for (const vuln of output.vulnerabilities.list) {
86
+ findings.push({
87
+ scanner: "cargo-audit",
88
+ ruleId: `cargo-audit:${vuln.advisory.id}`,
89
+ file: "Cargo.lock",
90
+ line: 1,
91
+ message: `${vuln.advisory.title} in ${vuln.package.name}@${vuln.package.version}`,
92
+ severity: mapAuditSeverity(vuln.advisory.severity),
93
+ confidence: 100,
94
+ metadata: {
95
+ package: vuln.package.name,
96
+ version: vuln.package.version,
97
+ advisoryUrl: vuln.advisory.url,
98
+ patchedVersions: vuln.versions.patched,
99
+ cvss: vuln.advisory.cvss,
100
+ description: vuln.advisory.description,
101
+ },
102
+ });
103
+ }
104
+ // Add warnings for unmaintained packages
105
+ for (const warn of output.warnings.unmaintained || []) {
106
+ findings.push({
107
+ scanner: "cargo-audit",
108
+ ruleId: `cargo-audit:${warn.advisory.id}`,
109
+ file: "Cargo.lock",
110
+ line: 1,
111
+ message: `Unmaintained package: ${warn.package.name}@${warn.package.version} - ${warn.advisory.title}`,
112
+ severity: "low",
113
+ confidence: 100,
114
+ metadata: {
115
+ package: warn.package.name,
116
+ version: warn.package.version,
117
+ type: "unmaintained",
118
+ },
119
+ });
120
+ }
121
+ return {
122
+ scanner: "cargo-audit",
123
+ findings,
124
+ duration: Date.now() - startTime,
125
+ success: true,
126
+ version: availability.version,
127
+ };
128
+ }
129
+ catch (error) {
130
+ return {
131
+ scanner: "cargo-audit",
132
+ findings: [],
133
+ duration: Date.now() - startTime,
134
+ success: false,
135
+ error: error instanceof Error ? error.message : "Unknown error",
136
+ };
137
+ }
138
+ }
139
+ export async function runClippy(projectPath, options) {
140
+ const startTime = Date.now();
141
+ try {
142
+ const availability = await checkClippyAvailable();
143
+ if (!availability.available) {
144
+ return {
145
+ scanner: "clippy",
146
+ findings: [],
147
+ duration: Date.now() - startTime,
148
+ success: false,
149
+ error: availability.error,
150
+ };
151
+ }
152
+ const { stdout, stderr } = await execAsync(`cd "${projectPath}" && cargo clippy --message-format=json -- -W clippy::all -W clippy::pedantic -W clippy::nursery 2>&1`, {
153
+ timeout: options?.timeout || 300000,
154
+ maxBuffer: 50 * 1024 * 1024,
155
+ }).catch((error) => {
156
+ if (error.stdout) {
157
+ return { stdout: error.stdout, stderr: error.stderr || "" };
158
+ }
159
+ throw error;
160
+ });
161
+ const findings = [];
162
+ const lines = stdout.split("\n").filter((l) => l.trim());
163
+ for (const line of lines) {
164
+ try {
165
+ const msg = JSON.parse(line);
166
+ if (msg.reason === "compiler-message" && msg.message && msg.message.spans?.length > 0) {
167
+ const primarySpan = msg.message.spans.find((s) => s.is_primary) || msg.message.spans[0];
168
+ // Only include security-relevant lints
169
+ const code = msg.message.code?.code || "";
170
+ const isSecurityRelevant = code.includes("unsafe") ||
171
+ code.includes("panic") ||
172
+ code.includes("unwrap") ||
173
+ code.includes("expect") ||
174
+ code.includes("transmute") ||
175
+ msg.message.level === "error";
176
+ if (isSecurityRelevant) {
177
+ findings.push({
178
+ scanner: "clippy",
179
+ ruleId: `clippy:${code}`,
180
+ file: primarySpan.file_name.replace(projectPath + "/", ""),
181
+ line: primarySpan.line_start,
182
+ endLine: primarySpan.line_end,
183
+ column: primarySpan.column_start,
184
+ message: msg.message.message,
185
+ severity: msg.message.level === "error" ? "high" : "medium",
186
+ confidence: 100,
187
+ evidence: primarySpan.text?.[0]?.text,
188
+ });
189
+ }
190
+ }
191
+ }
192
+ catch {
193
+ // Skip non-JSON lines
194
+ }
195
+ }
196
+ return {
197
+ scanner: "clippy",
198
+ findings,
199
+ duration: Date.now() - startTime,
200
+ success: true,
201
+ version: availability.version,
202
+ };
203
+ }
204
+ catch (error) {
205
+ return {
206
+ scanner: "clippy",
207
+ findings: [],
208
+ duration: Date.now() - startTime,
209
+ success: false,
210
+ error: error instanceof Error ? error.message : "Unknown error",
211
+ };
212
+ }
213
+ }
214
+ export async function runRustScanners(projectPath, options) {
215
+ const startTime = Date.now();
216
+ const [auditResult, clippyResult] = await Promise.all([
217
+ runCargoAudit(projectPath, options),
218
+ runClippy(projectPath, options),
219
+ ]);
220
+ const findings = [...auditResult.findings, ...clippyResult.findings];
221
+ const success = auditResult.success || clippyResult.success;
222
+ return {
223
+ scanner: "rust",
224
+ findings,
225
+ duration: Date.now() - startTime,
226
+ success,
227
+ error: !success ? "No Rust scanners available" : undefined,
228
+ };
229
+ }
230
+ export async function detectRust(projectPath) {
231
+ try {
232
+ await access(join(projectPath, "Cargo.toml"));
233
+ return true;
234
+ }
235
+ catch {
236
+ return false;
237
+ }
238
+ }
239
+ //# sourceMappingURL=rust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust.js","sourceRoot":"","sources":["../../src/scanners/rust.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Bottleneck Detector
3
+ *
4
+ * Analyzes load test results and code patterns to identify performance bottlenecks.
5
+ *
6
+ * @module scanners/scale/bottleneck-detector
7
+ */
8
+ import type { Bottleneck, LoadTestResult } from "./types.js";
9
+ /**
10
+ * Detect bottlenecks in a project
11
+ */
12
+ export declare function detectBottlenecks(projectPath: string, loadTestResults?: LoadTestResult): Promise<Bottleneck[]>;
13
+ /**
14
+ * Calculate bottleneck score (100 = no bottlenecks)
15
+ */
16
+ export declare function calculateBottleneckScore(bottlenecks: Bottleneck[]): number;
17
+ //# sourceMappingURL=bottleneck-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottleneck-detector.d.ts","sourceRoot":"","sources":["../../../src/scanners/scale/bottleneck-detector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA+M7D;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,cAAc,GAC/B,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BvB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAqB1E"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Bottleneck Detector
3
+ *
4
+ * Analyzes load test results and code patterns to identify performance bottlenecks.
5
+ *
6
+ * @module scanners/scale/bottleneck-detector
7
+ */
8
+ import { readFile, readdir } from "fs/promises";
9
+ import { join } from "path";
10
+ import { logger } from "../../logger.js";
11
+ /**
12
+ * N+1 query pattern detection
13
+ */
14
+ const N_PLUS_ONE_PATTERNS = [
15
+ // Prisma
16
+ /\.findMany\(\s*\{[^}]*include\s*:\s*\{/g,
17
+ // Sequelize
18
+ /\.findAll\(\s*\{[^}]*include\s*:\s*\[/g,
19
+ // TypeORM
20
+ /\.find\(\s*\{[^}]*relations\s*:\s*\[/g,
21
+ // Raw SQL in loop
22
+ /for\s*\([^)]*\)\s*\{[^}]*(?:SELECT|INSERT|UPDATE|DELETE)/gi,
23
+ // forEach with await
24
+ /\.forEach\(\s*async/g,
25
+ ];
26
+ /**
27
+ * Memory leak patterns
28
+ */
29
+ const MEMORY_LEAK_PATTERNS = [
30
+ // Growing arrays in closures
31
+ /const\s+\w+\s*=\s*\[\s*\][\s\S]*setInterval/g,
32
+ // Event listeners without cleanup
33
+ /addEventListener\([^)]+\)(?![\s\S]*removeEventListener)/g,
34
+ // Global state accumulation
35
+ /global\.\w+\s*=\s*\[[\s\S]*\.push\(/g,
36
+ ];
37
+ /**
38
+ * Blocking operation patterns
39
+ */
40
+ const BLOCKING_PATTERNS = [
41
+ // Sync file operations
42
+ /(?:readFileSync|writeFileSync|existsSync|statSync)/g,
43
+ // Blocking crypto
44
+ /crypto\.(?:pbkdf2Sync|scryptSync|randomBytes)\s*\(/g,
45
+ // Large JSON parsing
46
+ /JSON\.parse\([^)]*\.length\s*>\s*\d{6}/g,
47
+ ];
48
+ /**
49
+ * Analyze source code for potential bottlenecks
50
+ */
51
+ async function analyzeSourceCode(projectPath) {
52
+ const bottlenecks = [];
53
+ const srcDirs = ["src", "app", "pages", "api", "lib"];
54
+ for (const dir of srcDirs) {
55
+ try {
56
+ const dirPath = join(projectPath, dir);
57
+ const files = await readdir(dirPath, { recursive: true });
58
+ for (const file of files) {
59
+ if (typeof file !== "string")
60
+ continue;
61
+ if (!file.match(/\.(ts|js|tsx|jsx)$/))
62
+ continue;
63
+ try {
64
+ const filePath = join(dirPath, file);
65
+ const content = await readFile(filePath, "utf-8");
66
+ // Check for N+1 patterns
67
+ for (const pattern of N_PLUS_ONE_PATTERNS) {
68
+ const matches = content.match(pattern);
69
+ if (matches && matches.length > 0) {
70
+ bottlenecks.push({
71
+ type: "database",
72
+ location: `${dir}/${file}`,
73
+ severity: "high",
74
+ description: `Potential N+1 query pattern detected (${matches.length} occurrences)`,
75
+ metrics: {
76
+ current: matches.length,
77
+ threshold: 0,
78
+ unit: "patterns",
79
+ },
80
+ recommendation: "Consider using eager loading or batching queries",
81
+ });
82
+ }
83
+ }
84
+ // Check for memory leak patterns
85
+ for (const pattern of MEMORY_LEAK_PATTERNS) {
86
+ const matches = content.match(pattern);
87
+ if (matches && matches.length > 0) {
88
+ bottlenecks.push({
89
+ type: "memory",
90
+ location: `${dir}/${file}`,
91
+ severity: "medium",
92
+ description: `Potential memory leak pattern detected`,
93
+ metrics: {
94
+ current: matches.length,
95
+ threshold: 0,
96
+ unit: "patterns",
97
+ },
98
+ recommendation: "Ensure proper cleanup of resources and event listeners",
99
+ });
100
+ }
101
+ }
102
+ // Check for blocking patterns
103
+ for (const pattern of BLOCKING_PATTERNS) {
104
+ const matches = content.match(pattern);
105
+ if (matches && matches.length > 0) {
106
+ bottlenecks.push({
107
+ type: "cpu",
108
+ location: `${dir}/${file}`,
109
+ severity: "medium",
110
+ description: `Blocking operation detected: ${matches[0]}`,
111
+ metrics: {
112
+ current: matches.length,
113
+ threshold: 0,
114
+ unit: "occurrences",
115
+ },
116
+ recommendation: "Use async alternatives to avoid blocking the event loop",
117
+ });
118
+ }
119
+ }
120
+ }
121
+ catch {
122
+ // Skip files that can't be read
123
+ }
124
+ }
125
+ }
126
+ catch {
127
+ // Directory doesn't exist
128
+ }
129
+ }
130
+ return bottlenecks;
131
+ }
132
+ /**
133
+ * Analyze load test results for bottlenecks
134
+ */
135
+ function analyzeLoadTestResults(results) {
136
+ const bottlenecks = [];
137
+ // Check for high latency
138
+ if (results.summary.latency.p95 > 500) {
139
+ bottlenecks.push({
140
+ type: "endpoint",
141
+ location: "Overall API",
142
+ severity: results.summary.latency.p95 > 1000 ? "critical" : "high",
143
+ description: `High 95th percentile latency: ${results.summary.latency.p95.toFixed(0)}ms`,
144
+ metrics: {
145
+ current: results.summary.latency.p95,
146
+ threshold: 500,
147
+ unit: "ms",
148
+ },
149
+ recommendation: "Profile endpoints to identify slow operations, add caching, or optimize queries",
150
+ });
151
+ }
152
+ // Check for high error rate
153
+ if (results.summary.errorRate > 0.01) {
154
+ bottlenecks.push({
155
+ type: "endpoint",
156
+ location: "Overall API",
157
+ severity: results.summary.errorRate > 0.05 ? "critical" : "high",
158
+ description: `High error rate: ${(results.summary.errorRate * 100).toFixed(2)}%`,
159
+ metrics: {
160
+ current: results.summary.errorRate,
161
+ threshold: 0.01,
162
+ unit: "rate",
163
+ },
164
+ recommendation: "Check error logs, add retry logic, or scale resources",
165
+ });
166
+ }
167
+ // Check for low throughput
168
+ if (results.summary.avgThroughput < 100) {
169
+ bottlenecks.push({
170
+ type: "endpoint",
171
+ location: "Overall API",
172
+ severity: "medium",
173
+ description: `Low throughput: ${results.summary.avgThroughput.toFixed(1)} req/s`,
174
+ metrics: {
175
+ current: results.summary.avgThroughput,
176
+ threshold: 100,
177
+ unit: "req/s",
178
+ },
179
+ recommendation: "Consider horizontal scaling or optimizing request handling",
180
+ });
181
+ }
182
+ // Check individual endpoints
183
+ for (const scenario of results.scenarios) {
184
+ for (const endpoint of scenario.endpoints) {
185
+ if (endpoint.latency.p95 > 500) {
186
+ bottlenecks.push({
187
+ type: "endpoint",
188
+ location: `${endpoint.method} ${endpoint.path}`,
189
+ severity: endpoint.latency.p95 > 1000 ? "critical" : "high",
190
+ description: `Slow endpoint: p95=${endpoint.latency.p95.toFixed(0)}ms`,
191
+ metrics: {
192
+ current: endpoint.latency.p95,
193
+ threshold: 500,
194
+ unit: "ms",
195
+ },
196
+ recommendation: "Add endpoint-specific caching or optimize the handler",
197
+ });
198
+ }
199
+ }
200
+ }
201
+ return bottlenecks;
202
+ }
203
+ /**
204
+ * Detect bottlenecks in a project
205
+ */
206
+ export async function detectBottlenecks(projectPath, loadTestResults) {
207
+ const bottlenecks = [];
208
+ logger.info("scale.bottleneck_detection_started", { projectPath });
209
+ // Analyze source code
210
+ const codeBottlenecks = await analyzeSourceCode(projectPath);
211
+ bottlenecks.push(...codeBottlenecks);
212
+ // Analyze load test results if available
213
+ if (loadTestResults) {
214
+ const loadBottlenecks = analyzeLoadTestResults(loadTestResults);
215
+ bottlenecks.push(...loadBottlenecks);
216
+ }
217
+ // Sort by severity
218
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
219
+ bottlenecks.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
220
+ logger.info("scale.bottleneck_detection_completed", {
221
+ total: bottlenecks.length,
222
+ critical: bottlenecks.filter((b) => b.severity === "critical").length,
223
+ high: bottlenecks.filter((b) => b.severity === "high").length,
224
+ });
225
+ return bottlenecks;
226
+ }
227
+ /**
228
+ * Calculate bottleneck score (100 = no bottlenecks)
229
+ */
230
+ export function calculateBottleneckScore(bottlenecks) {
231
+ let score = 100;
232
+ for (const bottleneck of bottlenecks) {
233
+ switch (bottleneck.severity) {
234
+ case "critical":
235
+ score -= 25;
236
+ break;
237
+ case "high":
238
+ score -= 15;
239
+ break;
240
+ case "medium":
241
+ score -= 8;
242
+ break;
243
+ case "low":
244
+ score -= 3;
245
+ break;
246
+ }
247
+ }
248
+ return Math.max(0, score);
249
+ }
250
+ //# sourceMappingURL=bottleneck-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottleneck-detector.js","sourceRoot":"","sources":["../../../src/scanners/scale/bottleneck-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Capacity Estimator
3
+ *
4
+ * Estimates maximum capacity and projects costs based on load test results.
5
+ *
6
+ * @module scanners/scale/capacity-estimator
7
+ */
8
+ import type { CapacityEstimate, LoadTestResult, Bottleneck } from "./types.js";
9
+ /**
10
+ * Estimate capacity for a project
11
+ */
12
+ export declare function estimateCapacity(loadTestResult?: LoadTestResult, bottlenecks?: Bottleneck[]): Promise<CapacityEstimate>;
13
+ /**
14
+ * Calculate capacity score (100 = excellent capacity margin)
15
+ */
16
+ export declare function calculateCapacityScore(estimate: CapacityEstimate, targetConcurrent?: number): number;
17
+ //# sourceMappingURL=capacity-estimator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capacity-estimator.d.ts","sourceRoot":"","sources":["../../../src/scanners/scale/capacity-estimator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAiK/E;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,cAAc,CAAC,EAAE,cAAc,EAC/B,WAAW,GAAE,UAAU,EAAO,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAuC3B;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,gBAAgB,EAC1B,gBAAgB,GAAE,MAAY,GAC7B,MAAM,CAUR"}