@vibecheckai/cli 3.5.0 → 3.5.2

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 (224) hide show
  1. package/bin/registry.js +214 -237
  2. package/bin/runners/cli-utils.js +33 -2
  3. package/bin/runners/context/analyzer.js +52 -1
  4. package/bin/runners/context/generators/cursor.js +2 -49
  5. package/bin/runners/context/git-context.js +3 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/analysis-core.js +25 -5
  8. package/bin/runners/lib/analyzers.js +431 -481
  9. package/bin/runners/lib/default-config.js +127 -0
  10. package/bin/runners/lib/doctor/modules/security.js +3 -1
  11. package/bin/runners/lib/engine/ast-cache.js +210 -0
  12. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  13. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  14. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  15. package/bin/runners/lib/engine/env-extractor.js +207 -0
  16. package/bin/runners/lib/engine/express-extractor.js +208 -0
  17. package/bin/runners/lib/engine/extractors.js +849 -0
  18. package/bin/runners/lib/engine/index.js +207 -0
  19. package/bin/runners/lib/engine/repo-index.js +514 -0
  20. package/bin/runners/lib/engine/types.js +124 -0
  21. package/bin/runners/lib/engines/accessibility-engine.js +18 -218
  22. package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
  23. package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
  24. package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
  25. package/bin/runners/lib/engines/mock-data-engine.js +10 -53
  26. package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
  27. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
  28. package/bin/runners/lib/engines/type-aware-engine.js +39 -263
  29. package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
  30. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  31. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  32. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  33. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  34. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  35. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  36. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  37. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
  38. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  39. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  40. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  41. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  42. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  43. package/bin/runners/lib/entitlements-v2.js +73 -97
  44. package/bin/runners/lib/error-handler.js +44 -3
  45. package/bin/runners/lib/error-messages.js +289 -0
  46. package/bin/runners/lib/evidence-pack.js +7 -1
  47. package/bin/runners/lib/finding-id.js +69 -0
  48. package/bin/runners/lib/finding-sorter.js +89 -0
  49. package/bin/runners/lib/html-proof-report.js +700 -350
  50. package/bin/runners/lib/missions/plan.js +6 -46
  51. package/bin/runners/lib/missions/templates.js +0 -232
  52. package/bin/runners/lib/next-action.js +560 -0
  53. package/bin/runners/lib/prerequisites.js +149 -0
  54. package/bin/runners/lib/route-detection.js +137 -68
  55. package/bin/runners/lib/scan-output.js +91 -76
  56. package/bin/runners/lib/scan-runner.js +135 -0
  57. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  58. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  59. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  60. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  61. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  62. package/bin/runners/lib/schemas/validator.js +27 -0
  63. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  64. package/bin/runners/lib/ship-output-enterprise.js +23 -23
  65. package/bin/runners/lib/ship-output.js +75 -31
  66. package/bin/runners/lib/terminal-ui.js +6 -113
  67. package/bin/runners/lib/truth.js +351 -10
  68. package/bin/runners/lib/unified-cli-output.js +430 -603
  69. package/bin/runners/lib/unified-output.js +13 -9
  70. package/bin/runners/runAIAgent.js +10 -5
  71. package/bin/runners/runAgent.js +0 -3
  72. package/bin/runners/runAllowlist.js +389 -0
  73. package/bin/runners/runApprove.js +0 -33
  74. package/bin/runners/runAuth.js +73 -45
  75. package/bin/runners/runCheckpoint.js +51 -11
  76. package/bin/runners/runClassify.js +85 -21
  77. package/bin/runners/runContext.js +0 -3
  78. package/bin/runners/runDoctor.js +41 -28
  79. package/bin/runners/runEvidencePack.js +362 -0
  80. package/bin/runners/runFirewall.js +0 -3
  81. package/bin/runners/runFirewallHook.js +0 -3
  82. package/bin/runners/runFix.js +66 -76
  83. package/bin/runners/runGuard.js +18 -411
  84. package/bin/runners/runInit.js +113 -30
  85. package/bin/runners/runLabs.js +424 -0
  86. package/bin/runners/runMcp.js +19 -25
  87. package/bin/runners/runPolish.js +64 -240
  88. package/bin/runners/runPromptFirewall.js +12 -5
  89. package/bin/runners/runProve.js +57 -22
  90. package/bin/runners/runQuickstart.js +531 -0
  91. package/bin/runners/runReality.js +59 -68
  92. package/bin/runners/runReport.js +38 -33
  93. package/bin/runners/runRuntime.js +8 -5
  94. package/bin/runners/runScan.js +1413 -190
  95. package/bin/runners/runShip.js +113 -719
  96. package/bin/runners/runTruth.js +0 -3
  97. package/bin/runners/runValidate.js +13 -9
  98. package/bin/runners/runWatch.js +23 -14
  99. package/bin/scan.js +6 -1
  100. package/bin/vibecheck.js +204 -185
  101. package/mcp-server/deprecation-middleware.js +282 -0
  102. package/mcp-server/handlers/index.ts +15 -0
  103. package/mcp-server/handlers/tool-handler.ts +554 -0
  104. package/mcp-server/index-v1.js +698 -0
  105. package/mcp-server/index.js +210 -238
  106. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  107. package/mcp-server/lib/error-envelope.js +138 -0
  108. package/mcp-server/lib/executor.ts +499 -0
  109. package/mcp-server/lib/index.ts +19 -0
  110. package/mcp-server/lib/rate-limiter.js +166 -0
  111. package/mcp-server/lib/sandbox.test.ts +519 -0
  112. package/mcp-server/lib/sandbox.ts +395 -0
  113. package/mcp-server/lib/types.ts +267 -0
  114. package/mcp-server/package.json +12 -3
  115. package/mcp-server/registry/tool-registry.js +794 -0
  116. package/mcp-server/registry/tools.json +605 -0
  117. package/mcp-server/registry.test.ts +334 -0
  118. package/mcp-server/tests/tier-gating.test.js +297 -0
  119. package/mcp-server/tier-auth.js +378 -45
  120. package/mcp-server/tools-v3.js +353 -442
  121. package/mcp-server/tsconfig.json +37 -0
  122. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  123. package/package.json +1 -1
  124. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
  125. package/bin/runners/lib/audit-logger.js +0 -532
  126. package/bin/runners/lib/authority/authorities/architecture.js +0 -364
  127. package/bin/runners/lib/authority/authorities/compliance.js +0 -341
  128. package/bin/runners/lib/authority/authorities/human.js +0 -343
  129. package/bin/runners/lib/authority/authorities/quality.js +0 -420
  130. package/bin/runners/lib/authority/authorities/security.js +0 -228
  131. package/bin/runners/lib/authority/index.js +0 -293
  132. package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
  133. package/bin/runners/lib/cli-charts.js +0 -368
  134. package/bin/runners/lib/cli-config-display.js +0 -405
  135. package/bin/runners/lib/cli-demo.js +0 -275
  136. package/bin/runners/lib/cli-errors.js +0 -438
  137. package/bin/runners/lib/cli-help-formatter.js +0 -439
  138. package/bin/runners/lib/cli-interactive-menu.js +0 -509
  139. package/bin/runners/lib/cli-prompts.js +0 -441
  140. package/bin/runners/lib/cli-scan-cards.js +0 -362
  141. package/bin/runners/lib/compliance-reporter.js +0 -710
  142. package/bin/runners/lib/conductor/index.js +0 -671
  143. package/bin/runners/lib/easy/README.md +0 -123
  144. package/bin/runners/lib/easy/index.js +0 -140
  145. package/bin/runners/lib/easy/interactive-wizard.js +0 -788
  146. package/bin/runners/lib/easy/one-click-firewall.js +0 -564
  147. package/bin/runners/lib/easy/zero-config-reality.js +0 -714
  148. package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
  149. package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
  150. package/bin/runners/lib/engines/confidence-scoring.js +0 -276
  151. package/bin/runners/lib/engines/context-detection.js +0 -264
  152. package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
  153. package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
  154. package/bin/runners/lib/engines/env-variables-engine.js +0 -458
  155. package/bin/runners/lib/engines/error-handling-engine.js +0 -437
  156. package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
  157. package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
  158. package/bin/runners/lib/engines/framework-detection.js +0 -508
  159. package/bin/runners/lib/engines/import-order-engine.js +0 -429
  160. package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
  161. package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
  162. package/bin/runners/lib/engines/orchestrator.js +0 -334
  163. package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
  164. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
  165. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
  166. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
  167. package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
  168. package/bin/runners/lib/enhanced-features/index.js +0 -305
  169. package/bin/runners/lib/enhanced-output.js +0 -631
  170. package/bin/runners/lib/enterprise.js +0 -300
  171. package/bin/runners/lib/firewall/command-validator.js +0 -351
  172. package/bin/runners/lib/firewall/config.js +0 -341
  173. package/bin/runners/lib/firewall/content-validator.js +0 -519
  174. package/bin/runners/lib/firewall/index.js +0 -101
  175. package/bin/runners/lib/firewall/path-validator.js +0 -256
  176. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
  177. package/bin/runners/lib/mcp-utils.js +0 -425
  178. package/bin/runners/lib/output/index.js +0 -1022
  179. package/bin/runners/lib/policy-engine.js +0 -652
  180. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
  181. package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
  182. package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
  183. package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
  184. package/bin/runners/lib/polish/autofix/index.js +0 -200
  185. package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
  186. package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
  187. package/bin/runners/lib/polish/backend-checks.js +0 -148
  188. package/bin/runners/lib/polish/documentation-checks.js +0 -111
  189. package/bin/runners/lib/polish/frontend-checks.js +0 -168
  190. package/bin/runners/lib/polish/index.js +0 -71
  191. package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
  192. package/bin/runners/lib/polish/library-detection.js +0 -175
  193. package/bin/runners/lib/polish/performance-checks.js +0 -100
  194. package/bin/runners/lib/polish/security-checks.js +0 -148
  195. package/bin/runners/lib/polish/utils.js +0 -203
  196. package/bin/runners/lib/prompt-builder.js +0 -540
  197. package/bin/runners/lib/proof-certificate.js +0 -634
  198. package/bin/runners/lib/reality/accessibility-audit.js +0 -946
  199. package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
  200. package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
  201. package/bin/runners/lib/reality/performance-tracker.js +0 -1077
  202. package/bin/runners/lib/reality/scenario-generator.js +0 -1404
  203. package/bin/runners/lib/reality/visual-regression.js +0 -852
  204. package/bin/runners/lib/reality-profiler.js +0 -717
  205. package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
  206. package/bin/runners/lib/review/ai-code-review.js +0 -832
  207. package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
  208. package/bin/runners/lib/sbom-generator.js +0 -641
  209. package/bin/runners/lib/scan-output-enhanced.js +0 -512
  210. package/bin/runners/lib/security/owasp-scanner.js +0 -939
  211. package/bin/runners/lib/validators/contract-validator.js +0 -283
  212. package/bin/runners/lib/validators/dead-export-detector.js +0 -279
  213. package/bin/runners/lib/validators/dep-audit.js +0 -245
  214. package/bin/runners/lib/validators/env-validator.js +0 -319
  215. package/bin/runners/lib/validators/index.js +0 -120
  216. package/bin/runners/lib/validators/license-checker.js +0 -252
  217. package/bin/runners/lib/validators/route-validator.js +0 -290
  218. package/bin/runners/runAuthority.js +0 -528
  219. package/bin/runners/runConductor.js +0 -772
  220. package/bin/runners/runContainer.js +0 -366
  221. package/bin/runners/runEasy.js +0 -410
  222. package/bin/runners/runIaC.js +0 -372
  223. package/bin/runners/runVibe.js +0 -791
  224. package/mcp-server/tools.js +0 -495
@@ -1,161 +1,12 @@
1
1
  /**
2
2
  * API Consistency Engine
3
- * Enhanced with:
4
- * - REST convention checking (HTTP methods, response codes)
5
- * - Response shape consistency
6
- * - Input validation detection
7
- * - Error response format standardization
8
- * - CORS and security header detection
9
- * - Rate limiting indicators
10
- * - API versioning patterns
3
+ * Checks API route consistency, response formats, error handling patterns
11
4
  */
12
5
 
13
6
  const { getAST } = require("./ast-cache");
14
7
  const traverse = require("@babel/traverse").default;
15
8
  const t = require("@babel/types");
16
9
 
17
- /**
18
- * HTTP method best practices
19
- */
20
- const HTTP_METHOD_EXPECTATIONS = {
21
- GET: {
22
- shouldHaveBody: false,
23
- typicalStatusCodes: [200, 404],
24
- description: "Retrieve data",
25
- },
26
- POST: {
27
- shouldHaveBody: true,
28
- typicalStatusCodes: [201, 400, 409],
29
- description: "Create resource",
30
- },
31
- PUT: {
32
- shouldHaveBody: true,
33
- typicalStatusCodes: [200, 204, 404],
34
- description: "Replace resource",
35
- },
36
- PATCH: {
37
- shouldHaveBody: true,
38
- typicalStatusCodes: [200, 204, 404],
39
- description: "Update resource partially",
40
- },
41
- DELETE: {
42
- shouldHaveBody: false,
43
- typicalStatusCodes: [204, 404],
44
- description: "Remove resource",
45
- },
46
- };
47
-
48
- /**
49
- * Common response wrapper patterns
50
- */
51
- const RESPONSE_WRAPPER_PATTERNS = [
52
- { pattern: /\{\s*data\s*:/, name: "data" },
53
- { pattern: /\{\s*result\s*:/, name: "result" },
54
- { pattern: /\{\s*payload\s*:/, name: "payload" },
55
- { pattern: /\{\s*response\s*:/, name: "response" },
56
- { pattern: /\{\s*body\s*:/, name: "body" },
57
- { pattern: /\{\s*message\s*:/, name: "message" },
58
- { pattern: /\{\s*error\s*:/, name: "error" },
59
- { pattern: /\{\s*success\s*:/, name: "success" },
60
- ];
61
-
62
- /**
63
- * Detect HTTP method from file or code
64
- */
65
- function detectHTTPMethod(code, filePath) {
66
- const methods = new Set();
67
-
68
- // Next.js App Router pattern: export function GET/POST/etc
69
- const appRouterMatch = code.match(/export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g);
70
- if (appRouterMatch) {
71
- appRouterMatch.forEach(m => {
72
- const method = m.match(/(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)/)[1];
73
- methods.add(method);
74
- });
75
- }
76
-
77
- // Express pattern: app.get/post/etc or router.get/post/etc
78
- const expressMatch = code.match(/\.(get|post|put|patch|delete|head|options)\s*\(/gi);
79
- if (expressMatch) {
80
- expressMatch.forEach(m => {
81
- const method = m.match(/\.(get|post|put|patch|delete|head|options)/i)[1].toUpperCase();
82
- methods.add(method);
83
- });
84
- }
85
-
86
- // Next.js Pages Router pattern
87
- if (/req\.method\s*===?\s*['"](\w+)['"]/g.test(code)) {
88
- const methodMatch = code.match(/req\.method\s*===?\s*['"](\w+)['"]/g);
89
- methodMatch?.forEach(m => {
90
- const method = m.match(/['"](\w+)['"]/)[1].toUpperCase();
91
- methods.add(method);
92
- });
93
- }
94
-
95
- return methods;
96
- }
97
-
98
- /**
99
- * Check for input validation
100
- */
101
- function hasInputValidation(code) {
102
- const validationPatterns = [
103
- /\bzod\b/,
104
- /\byup\b/,
105
- /\bjoi\b/,
106
- /\bvalidate\s*\(/i,
107
- /\bschema\s*\.\s*parse/,
108
- /\bschema\s*\.\s*safeParse/,
109
- /\.input\s*\(/, // tRPC input
110
- /\bz\s*\.\s*object/,
111
- /\bz\s*\.\s*string/,
112
- /\bvalidateBody/i,
113
- /\brequestSchema/i,
114
- /\bbodySchema/i,
115
- ];
116
-
117
- return validationPatterns.some(p => p.test(code));
118
- }
119
-
120
- /**
121
- * Check for authentication
122
- */
123
- function hasAuthentication(code) {
124
- const authPatterns = [
125
- /getServerSession/,
126
- /getSession/,
127
- /auth\s*\(\)/,
128
- /verifyToken/,
129
- /authenticate/i,
130
- /authorization/i,
131
- /protectedProcedure/,
132
- /withAuth/i,
133
- /requireAuth/i,
134
- /isAuthenticated/i,
135
- /bearer/i,
136
- /jwt/i,
137
- ];
138
-
139
- return authPatterns.some(p => p.test(code));
140
- }
141
-
142
- /**
143
- * Check for rate limiting
144
- */
145
- function hasRateLimiting(code) {
146
- const rateLimitPatterns = [
147
- /rateLimit/i,
148
- /rateLimiter/i,
149
- /throttle/i,
150
- /X-RateLimit/i,
151
- /upstash.*ratelimit/i,
152
- /@upstash\/ratelimit/,
153
- /limiter\./i,
154
- ];
155
-
156
- return rateLimitPatterns.some(p => p.test(code));
157
- }
158
-
159
10
  /**
160
11
  * Analyze API consistency issues
161
12
  */
@@ -165,23 +16,13 @@ function analyzeAPIConsistency(code, filePath) {
165
16
  if (!ast) return findings;
166
17
 
167
18
  const lines = code.split("\n");
168
- const normalizedPath = filePath.replace(/\\/g, "/");
169
- const isAPIRoute = normalizedPath.includes("/api/") ||
170
- normalizedPath.includes("/routes/") ||
171
- normalizedPath.match(/\/route\.(ts|js)$/);
19
+ const isAPIRoute = filePath.includes("/api/") || filePath.includes("/routes/");
172
20
 
173
21
  if (!isAPIRoute) return findings;
174
22
 
175
23
  const responseFormats = new Set();
176
24
  const errorHandlingPatterns = new Set();
177
- const statusCodesUsed = new Set();
178
- const responseWrappers = new Set();
179
25
  let hasErrorHandler = false;
180
- let readsRequestBody = false;
181
- let hasContentTypeCheck = false;
182
-
183
- // Detect HTTP methods
184
- const httpMethods = detectHTTPMethod(code, filePath);
185
26
 
186
27
  traverse(ast, {
187
28
  // Check response formats
@@ -191,39 +32,18 @@ function analyzeAPIConsistency(code, filePath) {
191
32
  // Next.js API routes
192
33
  if (t.isMemberExpression(node.callee) &&
193
34
  t.isIdentifier(node.callee.object, { name: "NextResponse" })) {
194
- const method = node.callee.property?.name;
35
+ const method = node.callee.property.name;
195
36
  if (["json", "redirect", "next"].includes(method)) {
196
37
  responseFormats.add(`NextResponse.${method}`);
197
38
  }
198
-
199
- // Check response wrapper in NextResponse.json()
200
- if (method === "json" && node.arguments[0]) {
201
- const arg = node.arguments[0];
202
- if (t.isObjectExpression(arg)) {
203
- arg.properties.forEach(prop => {
204
- if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
205
- responseWrappers.add(prop.key.name);
206
- }
207
- });
208
- }
209
- }
210
39
  }
211
40
 
212
41
  // Express-style responses
213
42
  if (t.isMemberExpression(node.callee)) {
214
43
  const prop = node.callee.property;
215
- if (t.isIdentifier(prop)) {
216
- if (["json", "send", "status", "redirect"].includes(prop.name)) {
217
- responseFormats.add(`res.${prop.name}`);
218
- }
219
-
220
- // Track status codes
221
- if (prop.name === "status" && node.arguments[0]) {
222
- const statusArg = node.arguments[0];
223
- if (t.isNumericLiteral(statusArg)) {
224
- statusCodesUsed.add(statusArg.value);
225
- }
226
- }
44
+ if (t.isIdentifier(prop) &&
45
+ ["json", "send", "status", "redirect"].includes(prop.name)) {
46
+ responseFormats.add(`res.${prop.name}`);
227
47
  }
228
48
  }
229
49
 
@@ -233,43 +53,6 @@ function analyzeAPIConsistency(code, filePath) {
233
53
  hasErrorHandler = true;
234
54
  errorHandlingPatterns.add("promise.catch");
235
55
  }
236
-
237
- // Request body access
238
- if (t.isMemberExpression(node.callee)) {
239
- const obj = node.callee.object;
240
- const prop = node.callee.property;
241
-
242
- // req.body, request.json(), etc.
243
- if ((t.isIdentifier(obj, { name: "req" }) || t.isIdentifier(obj, { name: "request" })) &&
244
- t.isIdentifier(prop) && ["body", "json"].includes(prop.name)) {
245
- readsRequestBody = true;
246
- }
247
- }
248
-
249
- // Content-Type check
250
- if (t.isMemberExpression(node.callee)) {
251
- const callee = node.callee;
252
- if (t.isIdentifier(callee.property, { name: "get" }) &&
253
- node.arguments[0] &&
254
- t.isStringLiteral(node.arguments[0]) &&
255
- node.arguments[0].value.toLowerCase() === "content-type") {
256
- hasContentTypeCheck = true;
257
- }
258
- }
259
- },
260
-
261
- // Await request.json() also indicates body reading
262
- AwaitExpression(path) {
263
- const arg = path.node.argument;
264
- if (t.isCallExpression(arg) && t.isMemberExpression(arg.callee)) {
265
- const obj = arg.callee.object;
266
- const prop = arg.callee.property;
267
- if (t.isIdentifier(prop, { name: "json" }) ||
268
- t.isIdentifier(prop, { name: "formData" }) ||
269
- t.isIdentifier(prop, { name: "text" })) {
270
- readsRequestBody = true;
271
- }
272
- }
273
56
  },
274
57
 
275
58
  // Try-catch blocks
@@ -284,6 +67,7 @@ function analyzeAPIConsistency(code, filePath) {
284
67
  if (t.isBinaryExpression(test) &&
285
68
  (test.operator === "===" || test.operator === "==")) {
286
69
  const left = test.left;
70
+ const right = test.right;
287
71
 
288
72
  // Check for error status checks
289
73
  if ((t.isMemberExpression(left) &&
@@ -314,59 +98,18 @@ function analyzeAPIConsistency(code, filePath) {
314
98
  },
315
99
  });
316
100
 
317
- // REST convention checks
318
- for (const method of httpMethods) {
319
- const expectations = HTTP_METHOD_EXPECTATIONS[method];
320
- if (!expectations) continue;
321
-
322
- // Check GET/DELETE with body
323
- if (!expectations.shouldHaveBody && readsRequestBody) {
324
- findings.push({
325
- type: "rest_convention_violation",
326
- severity: "WARN",
327
- category: "APIConsistency",
328
- file: filePath,
329
- line: 1,
330
- column: 0,
331
- title: `${method} request should not have body`,
332
- message: `REST convention: ${method} requests typically don't have a request body. Consider using query parameters instead.`,
333
- confidence: "med",
334
- fixHint: "Use query parameters (searchParams) instead of request body for GET requests",
335
- });
336
- }
337
-
338
- // Check POST/PUT/PATCH without body
339
- if (expectations.shouldHaveBody && !readsRequestBody && method !== "DELETE") {
340
- findings.push({
341
- type: "rest_convention_violation",
342
- severity: "INFO",
343
- category: "APIConsistency",
344
- file: filePath,
345
- line: 1,
346
- column: 0,
347
- title: `${method} request without body`,
348
- message: `${method} requests typically include a request body. This might be intentional for some endpoints.`,
349
- confidence: "low",
350
- });
351
- }
352
- }
353
-
354
- // Check for inconsistent response wrappers
355
- const dataWrappers = Array.from(responseWrappers).filter(w =>
356
- ["data", "result", "payload", "response", "body"].includes(w)
357
- );
358
- if (dataWrappers.length > 1) {
101
+ // Check for inconsistent response formats
102
+ if (responseFormats.size > 1) {
359
103
  findings.push({
360
- type: "inconsistent_response_wrapper",
104
+ type: "inconsistent_response_format",
361
105
  severity: "WARN",
362
106
  category: "APIConsistency",
363
107
  file: filePath,
364
108
  line: 1,
365
109
  column: 0,
366
- title: "Inconsistent response wrapper keys",
367
- message: `Multiple response wrapper keys used: ${dataWrappers.join(", ")}. Standardize on one format.`,
368
- confidence: "med",
369
- fixHint: "Use a consistent wrapper like { data: ... } or { result: ... } across all endpoints",
110
+ title: "Inconsistent API response formats",
111
+ message: `Multiple response formats used: ${Array.from(responseFormats).join(", ")}`,
112
+ confidence: "low",
370
113
  });
371
114
  }
372
115
 
@@ -380,78 +123,34 @@ function analyzeAPIConsistency(code, filePath) {
380
123
  line: 1,
381
124
  column: 0,
382
125
  title: "API route missing error handling",
383
- message: "API route should have try-catch or promise error handling to prevent unhandled exceptions",
126
+ message: "API route should have try-catch or promise error handling",
384
127
  confidence: "med",
385
- fixHint: "Wrap async logic in try-catch and return appropriate error responses",
386
128
  });
387
129
  }
388
130
 
389
- // Check for missing input validation on POST/PUT/PATCH
390
- const mutationMethods = ["POST", "PUT", "PATCH"];
391
- const hasMutationMethod = mutationMethods.some(m => httpMethods.has(m));
392
-
393
- if (hasMutationMethod && readsRequestBody && !hasInputValidation(code)) {
394
- findings.push({
395
- type: "missing_input_validation",
396
- severity: "WARN",
397
- category: "APIConsistency",
398
- file: filePath,
399
- line: 1,
400
- column: 0,
401
- title: "API endpoint missing input validation",
402
- message: "Mutation endpoints should validate request body. Consider using Zod, Yup, or similar.",
403
- confidence: "med",
404
- fixHint: "Add schema validation: const body = schema.parse(await request.json())",
405
- });
406
- }
131
+ // Check for missing status codes
132
+ let hasStatusCode = false;
133
+ traverse(ast, {
134
+ CallExpression(path) {
135
+ const node = path.node;
136
+ if (t.isMemberExpression(node.callee) &&
137
+ t.isIdentifier(node.callee.property, { name: "status" })) {
138
+ hasStatusCode = true;
139
+ }
140
+ },
141
+ });
407
142
 
408
- // Check for missing authentication on sensitive endpoints
409
- const isSensitiveEndpoint = /\/(admin|user|account|settings|billing|payment)/i.test(normalizedPath);
410
- if (isSensitiveEndpoint && !hasAuthentication(code)) {
143
+ if (!hasStatusCode && responseFormats.size > 0) {
411
144
  findings.push({
412
- type: "missing_authentication",
145
+ type: "missing_status_code",
413
146
  severity: "WARN",
414
147
  category: "APIConsistency",
415
148
  file: filePath,
416
149
  line: 1,
417
150
  column: 0,
418
- title: "Sensitive endpoint may need authentication",
419
- message: `Endpoint path suggests sensitive data (${normalizedPath}). Consider adding authentication.`,
420
- confidence: "low",
421
- fixHint: "Add authentication check: const session = await getServerSession()",
422
- });
423
- }
424
-
425
- // Check for missing rate limiting on public endpoints
426
- const isPublicEndpoint = /(public|webhook|auth\/.*login|auth\/.*register)/i.test(normalizedPath);
427
- if (isPublicEndpoint && !hasRateLimiting(code)) {
428
- findings.push({
429
- type: "missing_rate_limiting",
430
- severity: "INFO",
431
- category: "APIConsistency",
432
- file: filePath,
433
- line: 1,
434
- column: 0,
435
- title: "Public endpoint without rate limiting",
436
- message: "Public endpoints should consider rate limiting to prevent abuse",
437
- confidence: "low",
438
- fixHint: "Consider using @upstash/ratelimit or similar rate limiting solution",
439
- });
440
- }
441
-
442
- // Check Content-Type validation for POST/PUT/PATCH
443
- if (hasMutationMethod && readsRequestBody && !hasContentTypeCheck) {
444
- // This is a low-priority check - most frameworks handle this
445
- findings.push({
446
- type: "missing_content_type_check",
447
- severity: "INFO",
448
- category: "APIConsistency",
449
- file: filePath,
450
- line: 1,
451
- column: 0,
452
- title: "No explicit Content-Type validation",
453
- message: "Consider validating Content-Type header for request body endpoints",
454
- confidence: "low",
151
+ title: "API response missing explicit status code",
152
+ message: "API responses should explicitly set HTTP status codes",
153
+ confidence: "med",
455
154
  });
456
155
  }
457
156
 
@@ -460,8 +159,4 @@ function analyzeAPIConsistency(code, filePath) {
460
159
 
461
160
  module.exports = {
462
161
  analyzeAPIConsistency,
463
- detectHTTPMethod,
464
- hasInputValidation,
465
- hasAuthentication,
466
- hasRateLimiting,
467
162
  };