@opensip-cli/checks-universal 0.1.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 (620) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/all-checks-execute.test.d.ts +17 -0
  5. package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
  6. package/dist/__tests__/all-checks-execute.test.js +452 -0
  7. package/dist/__tests__/all-checks-execute.test.js.map +1 -0
  8. package/dist/__tests__/behavior-fixtures-10.test.d.ts +8 -0
  9. package/dist/__tests__/behavior-fixtures-10.test.d.ts.map +1 -0
  10. package/dist/__tests__/behavior-fixtures-10.test.js +200 -0
  11. package/dist/__tests__/behavior-fixtures-10.test.js.map +1 -0
  12. package/dist/__tests__/behavior-fixtures-11.test.d.ts +8 -0
  13. package/dist/__tests__/behavior-fixtures-11.test.d.ts.map +1 -0
  14. package/dist/__tests__/behavior-fixtures-11.test.js +120 -0
  15. package/dist/__tests__/behavior-fixtures-11.test.js.map +1 -0
  16. package/dist/__tests__/behavior-fixtures-12.test.d.ts +8 -0
  17. package/dist/__tests__/behavior-fixtures-12.test.d.ts.map +1 -0
  18. package/dist/__tests__/behavior-fixtures-12.test.js +157 -0
  19. package/dist/__tests__/behavior-fixtures-12.test.js.map +1 -0
  20. package/dist/__tests__/behavior-fixtures-2.test.d.ts +8 -0
  21. package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
  22. package/dist/__tests__/behavior-fixtures-2.test.js +785 -0
  23. package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
  24. package/dist/__tests__/behavior-fixtures-3.test.d.ts +6 -0
  25. package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
  26. package/dist/__tests__/behavior-fixtures-3.test.js +663 -0
  27. package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
  28. package/dist/__tests__/behavior-fixtures-4.test.d.ts +5 -0
  29. package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
  30. package/dist/__tests__/behavior-fixtures-4.test.js +612 -0
  31. package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
  32. package/dist/__tests__/behavior-fixtures-5.test.d.ts +5 -0
  33. package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
  34. package/dist/__tests__/behavior-fixtures-5.test.js +469 -0
  35. package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
  36. package/dist/__tests__/behavior-fixtures-6.test.d.ts +8 -0
  37. package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
  38. package/dist/__tests__/behavior-fixtures-6.test.js +591 -0
  39. package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
  40. package/dist/__tests__/behavior-fixtures-7.test.d.ts +5 -0
  41. package/dist/__tests__/behavior-fixtures-7.test.d.ts.map +1 -0
  42. package/dist/__tests__/behavior-fixtures-7.test.js +662 -0
  43. package/dist/__tests__/behavior-fixtures-7.test.js.map +1 -0
  44. package/dist/__tests__/behavior-fixtures-8.test.d.ts +11 -0
  45. package/dist/__tests__/behavior-fixtures-8.test.d.ts.map +1 -0
  46. package/dist/__tests__/behavior-fixtures-8.test.js +634 -0
  47. package/dist/__tests__/behavior-fixtures-8.test.js.map +1 -0
  48. package/dist/__tests__/behavior-fixtures-9.test.d.ts +11 -0
  49. package/dist/__tests__/behavior-fixtures-9.test.d.ts.map +1 -0
  50. package/dist/__tests__/behavior-fixtures-9.test.js +271 -0
  51. package/dist/__tests__/behavior-fixtures-9.test.js.map +1 -0
  52. package/dist/__tests__/behavior-fixtures.test.d.ts +14 -0
  53. package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
  54. package/dist/__tests__/behavior-fixtures.test.js +1423 -0
  55. package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
  56. package/dist/__tests__/checks.test.d.ts +2 -0
  57. package/dist/__tests__/checks.test.d.ts.map +1 -0
  58. package/dist/__tests__/checks.test.js +61 -0
  59. package/dist/__tests__/checks.test.js.map +1 -0
  60. package/dist/__tests__/env-var-validation.test.d.ts +14 -0
  61. package/dist/__tests__/env-var-validation.test.d.ts.map +1 -0
  62. package/dist/__tests__/env-var-validation.test.js +53 -0
  63. package/dist/__tests__/env-var-validation.test.js.map +1 -0
  64. package/dist/__tests__/file-length-limit.test.d.ts +2 -0
  65. package/dist/__tests__/file-length-limit.test.d.ts.map +1 -0
  66. package/dist/__tests__/file-length-limit.test.js +29 -0
  67. package/dist/__tests__/file-length-limit.test.js.map +1 -0
  68. package/dist/__tests__/fixture-coverage.allowlist.d.ts +18 -0
  69. package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
  70. package/dist/__tests__/fixture-coverage.allowlist.js +35 -0
  71. package/dist/__tests__/fixture-coverage.allowlist.js.map +1 -0
  72. package/dist/__tests__/fixture-coverage.test.d.ts +13 -0
  73. package/dist/__tests__/fixture-coverage.test.d.ts.map +1 -0
  74. package/dist/__tests__/fixture-coverage.test.js +57 -0
  75. package/dist/__tests__/fixture-coverage.test.js.map +1 -0
  76. package/dist/__tests__/iic.test.d.ts +15 -0
  77. package/dist/__tests__/iic.test.d.ts.map +1 -0
  78. package/dist/__tests__/iic.test.js +316 -0
  79. package/dist/__tests__/iic.test.js.map +1 -0
  80. package/dist/__tests__/no-skipped-tests.test.d.ts +14 -0
  81. package/dist/__tests__/no-skipped-tests.test.d.ts.map +1 -0
  82. package/dist/__tests__/no-skipped-tests.test.js +144 -0
  83. package/dist/__tests__/no-skipped-tests.test.js.map +1 -0
  84. package/dist/__tests__/no-todo-comments.test.d.ts +2 -0
  85. package/dist/__tests__/no-todo-comments.test.d.ts.map +1 -0
  86. package/dist/__tests__/no-todo-comments.test.js +31 -0
  87. package/dist/__tests__/no-todo-comments.test.js.map +1 -0
  88. package/dist/__tests__/no-unimplemented-markers.test.d.ts +2 -0
  89. package/dist/__tests__/no-unimplemented-markers.test.d.ts.map +1 -0
  90. package/dist/__tests__/no-unimplemented-markers.test.js +140 -0
  91. package/dist/__tests__/no-unimplemented-markers.test.js.map +1 -0
  92. package/dist/__tests__/public-api-jsdoc-scope.test.d.ts +10 -0
  93. package/dist/__tests__/public-api-jsdoc-scope.test.d.ts.map +1 -0
  94. package/dist/__tests__/public-api-jsdoc-scope.test.js +176 -0
  95. package/dist/__tests__/public-api-jsdoc-scope.test.js.map +1 -0
  96. package/dist/__tests__/resilience-fp.test.d.ts +14 -0
  97. package/dist/__tests__/resilience-fp.test.d.ts.map +1 -0
  98. package/dist/__tests__/resilience-fp.test.js +110 -0
  99. package/dist/__tests__/resilience-fp.test.js.map +1 -0
  100. package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts +2 -0
  101. package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts.map +1 -0
  102. package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js +32 -0
  103. package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js.map +1 -0
  104. package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts +2 -0
  105. package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts.map +1 -0
  106. package/dist/checks/architecture/__tests__/tool-has-manifest.test.js +152 -0
  107. package/dist/checks/architecture/__tests__/tool-has-manifest.test.js.map +1 -0
  108. package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts +2 -0
  109. package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts.map +1 -0
  110. package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js +129 -0
  111. package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js.map +1 -0
  112. package/dist/checks/architecture/_yaml-doc-bindings.d.ts +23 -0
  113. package/dist/checks/architecture/_yaml-doc-bindings.d.ts.map +1 -0
  114. package/dist/checks/architecture/_yaml-doc-bindings.js +29 -0
  115. package/dist/checks/architecture/_yaml-doc-bindings.js.map +1 -0
  116. package/dist/checks/architecture/dependencies/index.d.ts +2 -0
  117. package/dist/checks/architecture/dependencies/index.d.ts.map +1 -0
  118. package/dist/checks/architecture/dependencies/index.js +2 -0
  119. package/dist/checks/architecture/dependencies/index.js.map +1 -0
  120. package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts +11 -0
  121. package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts.map +1 -0
  122. package/dist/checks/architecture/dependencies/no-duplicate-packages.js +171 -0
  123. package/dist/checks/architecture/dependencies/no-duplicate-packages.js.map +1 -0
  124. package/dist/checks/architecture/docker-best-practices.d.ts +23 -0
  125. package/dist/checks/architecture/docker-best-practices.d.ts.map +1 -0
  126. package/dist/checks/architecture/docker-best-practices.js +427 -0
  127. package/dist/checks/architecture/docker-best-practices.js.map +1 -0
  128. package/dist/checks/architecture/docker-ignore-validation.d.ts +18 -0
  129. package/dist/checks/architecture/docker-ignore-validation.d.ts.map +1 -0
  130. package/dist/checks/architecture/docker-ignore-validation.js +117 -0
  131. package/dist/checks/architecture/docker-ignore-validation.js.map +1 -0
  132. package/dist/checks/architecture/docker-version-sync.d.ts +16 -0
  133. package/dist/checks/architecture/docker-version-sync.d.ts.map +1 -0
  134. package/dist/checks/architecture/docker-version-sync.js +193 -0
  135. package/dist/checks/architecture/docker-version-sync.js.map +1 -0
  136. package/dist/checks/architecture/env-var-validation.d.ts +14 -0
  137. package/dist/checks/architecture/env-var-validation.d.ts.map +1 -0
  138. package/dist/checks/architecture/env-var-validation.js +289 -0
  139. package/dist/checks/architecture/env-var-validation.js.map +1 -0
  140. package/dist/checks/architecture/heavy-import-detection.d.ts +11 -0
  141. package/dist/checks/architecture/heavy-import-detection.d.ts.map +1 -0
  142. package/dist/checks/architecture/heavy-import-detection.js +91 -0
  143. package/dist/checks/architecture/heavy-import-detection.js.map +1 -0
  144. package/dist/checks/architecture/index.d.ts +16 -0
  145. package/dist/checks/architecture/index.d.ts.map +1 -0
  146. package/dist/checks/architecture/index.js +16 -0
  147. package/dist/checks/architecture/index.js.map +1 -0
  148. package/dist/checks/architecture/modules/empty-package-detection.d.ts +11 -0
  149. package/dist/checks/architecture/modules/empty-package-detection.d.ts.map +1 -0
  150. package/dist/checks/architecture/modules/empty-package-detection.js +277 -0
  151. package/dist/checks/architecture/modules/empty-package-detection.js.map +1 -0
  152. package/dist/checks/architecture/modules/index.d.ts +3 -0
  153. package/dist/checks/architecture/modules/index.d.ts.map +1 -0
  154. package/dist/checks/architecture/modules/index.js +3 -0
  155. package/dist/checks/architecture/modules/index.js.map +1 -0
  156. package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts +12 -0
  157. package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts.map +1 -0
  158. package/dist/checks/architecture/modules/interface-implementation-consistency.js +555 -0
  159. package/dist/checks/architecture/modules/interface-implementation-consistency.js.map +1 -0
  160. package/dist/checks/architecture/no-custom-event-emitter.d.ts +11 -0
  161. package/dist/checks/architecture/no-custom-event-emitter.d.ts.map +1 -0
  162. package/dist/checks/architecture/no-custom-event-emitter.js +123 -0
  163. package/dist/checks/architecture/no-custom-event-emitter.js.map +1 -0
  164. package/dist/checks/architecture/no-kebab-option-indexing.d.ts +33 -0
  165. package/dist/checks/architecture/no-kebab-option-indexing.d.ts.map +1 -0
  166. package/dist/checks/architecture/no-kebab-option-indexing.js +81 -0
  167. package/dist/checks/architecture/no-kebab-option-indexing.js.map +1 -0
  168. package/dist/checks/architecture/node-version-consistency.d.ts +22 -0
  169. package/dist/checks/architecture/node-version-consistency.d.ts.map +1 -0
  170. package/dist/checks/architecture/node-version-consistency.js +225 -0
  171. package/dist/checks/architecture/node-version-consistency.js.map +1 -0
  172. package/dist/checks/architecture/project-readme-existence.d.ts +13 -0
  173. package/dist/checks/architecture/project-readme-existence.d.ts.map +1 -0
  174. package/dist/checks/architecture/project-readme-existence.js +55 -0
  175. package/dist/checks/architecture/project-readme-existence.js.map +1 -0
  176. package/dist/checks/architecture/stale-build-artifacts.d.ts +10 -0
  177. package/dist/checks/architecture/stale-build-artifacts.d.ts.map +1 -0
  178. package/dist/checks/architecture/stale-build-artifacts.js +55 -0
  179. package/dist/checks/architecture/stale-build-artifacts.js.map +1 -0
  180. package/dist/checks/architecture/tool-has-manifest.d.ts +27 -0
  181. package/dist/checks/architecture/tool-has-manifest.d.ts.map +1 -0
  182. package/dist/checks/architecture/tool-has-manifest.js +135 -0
  183. package/dist/checks/architecture/tool-has-manifest.js.map +1 -0
  184. package/dist/checks/architecture/vitest-config-extends-base.d.ts +15 -0
  185. package/dist/checks/architecture/vitest-config-extends-base.d.ts.map +1 -0
  186. package/dist/checks/architecture/vitest-config-extends-base.js +104 -0
  187. package/dist/checks/architecture/vitest-config-extends-base.js.map +1 -0
  188. package/dist/checks/architecture/vitest-config-required-with-tests.d.ts +49 -0
  189. package/dist/checks/architecture/vitest-config-required-with-tests.d.ts.map +1 -0
  190. package/dist/checks/architecture/vitest-config-required-with-tests.js +199 -0
  191. package/dist/checks/architecture/vitest-config-required-with-tests.js.map +1 -0
  192. package/dist/checks/documentation/_directives/eslint.d.ts +9 -0
  193. package/dist/checks/documentation/_directives/eslint.d.ts.map +1 -0
  194. package/dist/checks/documentation/_directives/eslint.js +168 -0
  195. package/dist/checks/documentation/_directives/eslint.js.map +1 -0
  196. package/dist/checks/documentation/_directives/fitness.d.ts +9 -0
  197. package/dist/checks/documentation/_directives/fitness.d.ts.map +1 -0
  198. package/dist/checks/documentation/_directives/fitness.js +64 -0
  199. package/dist/checks/documentation/_directives/fitness.js.map +1 -0
  200. package/dist/checks/documentation/_directives/graph.d.ts +10 -0
  201. package/dist/checks/documentation/_directives/graph.d.ts.map +1 -0
  202. package/dist/checks/documentation/_directives/graph.js +65 -0
  203. package/dist/checks/documentation/_directives/graph.js.map +1 -0
  204. package/dist/checks/documentation/_directives/graph.test.d.ts +2 -0
  205. package/dist/checks/documentation/_directives/graph.test.d.ts.map +1 -0
  206. package/dist/checks/documentation/_directives/graph.test.js +54 -0
  207. package/dist/checks/documentation/_directives/graph.test.js.map +1 -0
  208. package/dist/checks/documentation/_directives/semgrep.d.ts +8 -0
  209. package/dist/checks/documentation/_directives/semgrep.d.ts.map +1 -0
  210. package/dist/checks/documentation/_directives/semgrep.js +72 -0
  211. package/dist/checks/documentation/_directives/semgrep.js.map +1 -0
  212. package/dist/checks/documentation/_directives/types.d.ts +21 -0
  213. package/dist/checks/documentation/_directives/types.d.ts.map +1 -0
  214. package/dist/checks/documentation/_directives/types.js +9 -0
  215. package/dist/checks/documentation/_directives/types.js.map +1 -0
  216. package/dist/checks/documentation/_directives/typescript.d.ts +10 -0
  217. package/dist/checks/documentation/_directives/typescript.d.ts.map +1 -0
  218. package/dist/checks/documentation/_directives/typescript.js +54 -0
  219. package/dist/checks/documentation/_directives/typescript.js.map +1 -0
  220. package/dist/checks/documentation/_public-api-graph.d.ts +30 -0
  221. package/dist/checks/documentation/_public-api-graph.d.ts.map +1 -0
  222. package/dist/checks/documentation/_public-api-graph.js +304 -0
  223. package/dist/checks/documentation/_public-api-graph.js.map +1 -0
  224. package/dist/checks/documentation/directive-audit.d.ts +26 -0
  225. package/dist/checks/documentation/directive-audit.d.ts.map +1 -0
  226. package/dist/checks/documentation/directive-audit.js +144 -0
  227. package/dist/checks/documentation/directive-audit.js.map +1 -0
  228. package/dist/checks/documentation/index.d.ts +3 -0
  229. package/dist/checks/documentation/index.d.ts.map +1 -0
  230. package/dist/checks/documentation/index.js +3 -0
  231. package/dist/checks/documentation/index.js.map +1 -0
  232. package/dist/checks/documentation/public-api-jsdoc.d.ts +10 -0
  233. package/dist/checks/documentation/public-api-jsdoc.d.ts.map +1 -0
  234. package/dist/checks/documentation/public-api-jsdoc.js +131 -0
  235. package/dist/checks/documentation/public-api-jsdoc.js.map +1 -0
  236. package/dist/checks/file-length-limit.d.ts +16 -0
  237. package/dist/checks/file-length-limit.d.ts.map +1 -0
  238. package/dist/checks/file-length-limit.js +47 -0
  239. package/dist/checks/file-length-limit.js.map +1 -0
  240. package/dist/checks/index.d.ts +16 -0
  241. package/dist/checks/index.d.ts.map +1 -0
  242. package/dist/checks/index.js +16 -0
  243. package/dist/checks/index.js.map +1 -0
  244. package/dist/checks/no-todo-comments.d.ts +18 -0
  245. package/dist/checks/no-todo-comments.d.ts.map +1 -0
  246. package/dist/checks/no-todo-comments.js +79 -0
  247. package/dist/checks/no-todo-comments.js.map +1 -0
  248. package/dist/checks/no-unimplemented-markers.d.ts +24 -0
  249. package/dist/checks/no-unimplemented-markers.d.ts.map +1 -0
  250. package/dist/checks/no-unimplemented-markers.js +198 -0
  251. package/dist/checks/no-unimplemented-markers.js.map +1 -0
  252. package/dist/checks/quality/api/graphql-offset-pagination.d.ts +9 -0
  253. package/dist/checks/quality/api/graphql-offset-pagination.d.ts.map +1 -0
  254. package/dist/checks/quality/api/graphql-offset-pagination.js +63 -0
  255. package/dist/checks/quality/api/graphql-offset-pagination.js.map +1 -0
  256. package/dist/checks/quality/api/index.d.ts +3 -0
  257. package/dist/checks/quality/api/index.d.ts.map +1 -0
  258. package/dist/checks/quality/api/index.js +3 -0
  259. package/dist/checks/quality/api/index.js.map +1 -0
  260. package/dist/checks/quality/api/zod-openapi-sync.d.ts +13 -0
  261. package/dist/checks/quality/api/zod-openapi-sync.d.ts.map +1 -0
  262. package/dist/checks/quality/api/zod-openapi-sync.js +88 -0
  263. package/dist/checks/quality/api/zod-openapi-sync.js.map +1 -0
  264. package/dist/checks/quality/code-structure/dead-code.d.ts +12 -0
  265. package/dist/checks/quality/code-structure/dead-code.d.ts.map +1 -0
  266. package/dist/checks/quality/code-structure/dead-code.js +238 -0
  267. package/dist/checks/quality/code-structure/dead-code.js.map +1 -0
  268. package/dist/checks/quality/code-structure/index.d.ts +5 -0
  269. package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
  270. package/dist/checks/quality/code-structure/index.js +5 -0
  271. package/dist/checks/quality/code-structure/index.js.map +1 -0
  272. package/dist/checks/quality/code-structure/no-ai-attribution.d.ts +25 -0
  273. package/dist/checks/quality/code-structure/no-ai-attribution.d.ts.map +1 -0
  274. package/dist/checks/quality/code-structure/no-ai-attribution.js +76 -0
  275. package/dist/checks/quality/code-structure/no-ai-attribution.js.map +1 -0
  276. package/dist/checks/quality/code-structure/no-console-log.d.ts +17 -0
  277. package/dist/checks/quality/code-structure/no-console-log.d.ts.map +1 -0
  278. package/dist/checks/quality/code-structure/no-console-log.js +106 -0
  279. package/dist/checks/quality/code-structure/no-console-log.js.map +1 -0
  280. package/dist/checks/quality/code-structure/no-process-artifacts.d.ts +25 -0
  281. package/dist/checks/quality/code-structure/no-process-artifacts.d.ts.map +1 -0
  282. package/dist/checks/quality/code-structure/no-process-artifacts.js +104 -0
  283. package/dist/checks/quality/code-structure/no-process-artifacts.js.map +1 -0
  284. package/dist/checks/quality/dependency-version-consistency.d.ts +20 -0
  285. package/dist/checks/quality/dependency-version-consistency.d.ts.map +1 -0
  286. package/dist/checks/quality/dependency-version-consistency.js +266 -0
  287. package/dist/checks/quality/dependency-version-consistency.js.map +1 -0
  288. package/dist/checks/quality/fitness-ignore-hygiene.d.ts +10 -0
  289. package/dist/checks/quality/fitness-ignore-hygiene.d.ts.map +1 -0
  290. package/dist/checks/quality/fitness-ignore-hygiene.js +93 -0
  291. package/dist/checks/quality/fitness-ignore-hygiene.js.map +1 -0
  292. package/dist/checks/quality/frontend/expo-vector-icons.d.ts +13 -0
  293. package/dist/checks/quality/frontend/expo-vector-icons.d.ts.map +1 -0
  294. package/dist/checks/quality/frontend/expo-vector-icons.js +80 -0
  295. package/dist/checks/quality/frontend/expo-vector-icons.js.map +1 -0
  296. package/dist/checks/quality/frontend/image-optimization.d.ts +13 -0
  297. package/dist/checks/quality/frontend/image-optimization.d.ts.map +1 -0
  298. package/dist/checks/quality/frontend/image-optimization.js +166 -0
  299. package/dist/checks/quality/frontend/image-optimization.js.map +1 -0
  300. package/dist/checks/quality/frontend/index.d.ts +4 -0
  301. package/dist/checks/quality/frontend/index.d.ts.map +1 -0
  302. package/dist/checks/quality/frontend/index.js +4 -0
  303. package/dist/checks/quality/frontend/index.js.map +1 -0
  304. package/dist/checks/quality/frontend/navigation-typing.d.ts +12 -0
  305. package/dist/checks/quality/frontend/navigation-typing.d.ts.map +1 -0
  306. package/dist/checks/quality/frontend/navigation-typing.js +77 -0
  307. package/dist/checks/quality/frontend/navigation-typing.js.map +1 -0
  308. package/dist/checks/quality/graph-ignore-hygiene.d.ts +10 -0
  309. package/dist/checks/quality/graph-ignore-hygiene.d.ts.map +1 -0
  310. package/dist/checks/quality/graph-ignore-hygiene.js +95 -0
  311. package/dist/checks/quality/graph-ignore-hygiene.js.map +1 -0
  312. package/dist/checks/quality/graph-ignore-hygiene.test.d.ts +14 -0
  313. package/dist/checks/quality/graph-ignore-hygiene.test.d.ts.map +1 -0
  314. package/dist/checks/quality/graph-ignore-hygiene.test.js +58 -0
  315. package/dist/checks/quality/graph-ignore-hygiene.test.js.map +1 -0
  316. package/dist/checks/quality/index.d.ts +16 -0
  317. package/dist/checks/quality/index.d.ts.map +1 -0
  318. package/dist/checks/quality/index.js +16 -0
  319. package/dist/checks/quality/index.js.map +1 -0
  320. package/dist/checks/quality/linting/eslint-justifications.d.ts +12 -0
  321. package/dist/checks/quality/linting/eslint-justifications.d.ts.map +1 -0
  322. package/dist/checks/quality/linting/eslint-justifications.js +328 -0
  323. package/dist/checks/quality/linting/eslint-justifications.js.map +1 -0
  324. package/dist/checks/quality/linting/index.d.ts +4 -0
  325. package/dist/checks/quality/linting/index.d.ts.map +1 -0
  326. package/dist/checks/quality/linting/index.js +4 -0
  327. package/dist/checks/quality/linting/index.js.map +1 -0
  328. package/dist/checks/quality/linting/semgrep-justifications.d.ts +16 -0
  329. package/dist/checks/quality/linting/semgrep-justifications.d.ts.map +1 -0
  330. package/dist/checks/quality/linting/semgrep-justifications.js +229 -0
  331. package/dist/checks/quality/linting/semgrep-justifications.js.map +1 -0
  332. package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts +12 -0
  333. package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts.map +1 -0
  334. package/dist/checks/quality/linting/typescript-directive-hygiene.js +142 -0
  335. package/dist/checks/quality/linting/typescript-directive-hygiene.js.map +1 -0
  336. package/dist/checks/quality/no-compatibility-layer-names.d.ts +13 -0
  337. package/dist/checks/quality/no-compatibility-layer-names.d.ts.map +1 -0
  338. package/dist/checks/quality/no-compatibility-layer-names.js +100 -0
  339. package/dist/checks/quality/no-compatibility-layer-names.js.map +1 -0
  340. package/dist/checks/quality/no-deprecated-tags.d.ts +11 -0
  341. package/dist/checks/quality/no-deprecated-tags.d.ts.map +1 -0
  342. package/dist/checks/quality/no-deprecated-tags.js +76 -0
  343. package/dist/checks/quality/no-deprecated-tags.js.map +1 -0
  344. package/dist/checks/quality/no-markdown-references.d.ts +16 -0
  345. package/dist/checks/quality/no-markdown-references.d.ts.map +1 -0
  346. package/dist/checks/quality/no-markdown-references.js +145 -0
  347. package/dist/checks/quality/no-markdown-references.js.map +1 -0
  348. package/dist/checks/quality/no-raw-regex-on-code.d.ts +9 -0
  349. package/dist/checks/quality/no-raw-regex-on-code.d.ts.map +1 -0
  350. package/dist/checks/quality/no-raw-regex-on-code.js +61 -0
  351. package/dist/checks/quality/no-raw-regex-on-code.js.map +1 -0
  352. package/dist/checks/quality/no-temporary-workarounds.d.ts +11 -0
  353. package/dist/checks/quality/no-temporary-workarounds.d.ts.map +1 -0
  354. package/dist/checks/quality/no-temporary-workarounds.js +69 -0
  355. package/dist/checks/quality/no-temporary-workarounds.js.map +1 -0
  356. package/dist/checks/quality/no-window-alert.d.ts +19 -0
  357. package/dist/checks/quality/no-window-alert.d.ts.map +1 -0
  358. package/dist/checks/quality/no-window-alert.js +74 -0
  359. package/dist/checks/quality/no-window-alert.js.map +1 -0
  360. package/dist/checks/quality/observability/index.d.ts +2 -0
  361. package/dist/checks/quality/observability/index.d.ts.map +1 -0
  362. package/dist/checks/quality/observability/index.js +2 -0
  363. package/dist/checks/quality/observability/index.js.map +1 -0
  364. package/dist/checks/quality/observability/pino-serializer-coverage.d.ts +15 -0
  365. package/dist/checks/quality/observability/pino-serializer-coverage.d.ts.map +1 -0
  366. package/dist/checks/quality/observability/pino-serializer-coverage.js +209 -0
  367. package/dist/checks/quality/observability/pino-serializer-coverage.js.map +1 -0
  368. package/dist/checks/quality/patterns/async-state-pattern.d.ts +14 -0
  369. package/dist/checks/quality/patterns/async-state-pattern.d.ts.map +1 -0
  370. package/dist/checks/quality/patterns/async-state-pattern.js +80 -0
  371. package/dist/checks/quality/patterns/async-state-pattern.js.map +1 -0
  372. package/dist/checks/quality/patterns/index.d.ts +4 -0
  373. package/dist/checks/quality/patterns/index.d.ts.map +1 -0
  374. package/dist/checks/quality/patterns/index.js +4 -0
  375. package/dist/checks/quality/patterns/index.js.map +1 -0
  376. package/dist/checks/quality/patterns/no-non-null-assertions.d.ts +10 -0
  377. package/dist/checks/quality/patterns/no-non-null-assertions.d.ts.map +1 -0
  378. package/dist/checks/quality/patterns/no-non-null-assertions.js +97 -0
  379. package/dist/checks/quality/patterns/no-non-null-assertions.js.map +1 -0
  380. package/dist/checks/quality/patterns/performance-anti-patterns.d.ts +16 -0
  381. package/dist/checks/quality/patterns/performance-anti-patterns.d.ts.map +1 -0
  382. package/dist/checks/quality/patterns/performance-anti-patterns.js +239 -0
  383. package/dist/checks/quality/patterns/performance-anti-patterns.js.map +1 -0
  384. package/dist/checks/resilience/_helpers/config-validation.d.ts +27 -0
  385. package/dist/checks/resilience/_helpers/config-validation.d.ts.map +1 -0
  386. package/dist/checks/resilience/_helpers/config-validation.js +61 -0
  387. package/dist/checks/resilience/_helpers/config-validation.js.map +1 -0
  388. package/dist/checks/resilience/batch-operations.d.ts +22 -0
  389. package/dist/checks/resilience/batch-operations.d.ts.map +1 -0
  390. package/dist/checks/resilience/batch-operations.js +422 -0
  391. package/dist/checks/resilience/batch-operations.js.map +1 -0
  392. package/dist/checks/resilience/cache-ttl-validation.d.ts +13 -0
  393. package/dist/checks/resilience/cache-ttl-validation.d.ts.map +1 -0
  394. package/dist/checks/resilience/cache-ttl-validation.js +222 -0
  395. package/dist/checks/resilience/cache-ttl-validation.js.map +1 -0
  396. package/dist/checks/resilience/catch-clause-safety.d.ts +12 -0
  397. package/dist/checks/resilience/catch-clause-safety.d.ts.map +1 -0
  398. package/dist/checks/resilience/catch-clause-safety.js +110 -0
  399. package/dist/checks/resilience/catch-clause-safety.js.map +1 -0
  400. package/dist/checks/resilience/dangerous-config-defaults.d.ts +11 -0
  401. package/dist/checks/resilience/dangerous-config-defaults.d.ts.map +1 -0
  402. package/dist/checks/resilience/dangerous-config-defaults.js +304 -0
  403. package/dist/checks/resilience/dangerous-config-defaults.js.map +1 -0
  404. package/dist/checks/resilience/error-code-registration.d.ts +11 -0
  405. package/dist/checks/resilience/error-code-registration.d.ts.map +1 -0
  406. package/dist/checks/resilience/error-code-registration.js +88 -0
  407. package/dist/checks/resilience/error-code-registration.js.map +1 -0
  408. package/dist/checks/resilience/event-patterns.d.ts +21 -0
  409. package/dist/checks/resilience/event-patterns.d.ts.map +1 -0
  410. package/dist/checks/resilience/event-patterns.js +232 -0
  411. package/dist/checks/resilience/event-patterns.js.map +1 -0
  412. package/dist/checks/resilience/exit-code-correctness.d.ts +12 -0
  413. package/dist/checks/resilience/exit-code-correctness.d.ts.map +1 -0
  414. package/dist/checks/resilience/exit-code-correctness.js +107 -0
  415. package/dist/checks/resilience/exit-code-correctness.js.map +1 -0
  416. package/dist/checks/resilience/index.d.ts +18 -0
  417. package/dist/checks/resilience/index.d.ts.map +1 -0
  418. package/dist/checks/resilience/index.js +18 -0
  419. package/dist/checks/resilience/index.js.map +1 -0
  420. package/dist/checks/resilience/no-hardcoded-timeouts.d.ts +10 -0
  421. package/dist/checks/resilience/no-hardcoded-timeouts.d.ts.map +1 -0
  422. package/dist/checks/resilience/no-hardcoded-timeouts.js +291 -0
  423. package/dist/checks/resilience/no-hardcoded-timeouts.js.map +1 -0
  424. package/dist/checks/resilience/no-process-exit-in-finally.d.ts +11 -0
  425. package/dist/checks/resilience/no-process-exit-in-finally.d.ts.map +1 -0
  426. package/dist/checks/resilience/no-process-exit-in-finally.js +89 -0
  427. package/dist/checks/resilience/no-process-exit-in-finally.js.map +1 -0
  428. package/dist/checks/resilience/readline-cleanup.d.ts +11 -0
  429. package/dist/checks/resilience/readline-cleanup.d.ts.map +1 -0
  430. package/dist/checks/resilience/readline-cleanup.js +107 -0
  431. package/dist/checks/resilience/readline-cleanup.js.map +1 -0
  432. package/dist/checks/resilience/recovery-patterns.d.ts +25 -0
  433. package/dist/checks/resilience/recovery-patterns.d.ts.map +1 -0
  434. package/dist/checks/resilience/recovery-patterns.js +273 -0
  435. package/dist/checks/resilience/recovery-patterns.js.map +1 -0
  436. package/dist/checks/resilience/reentrancy-guard.d.ts +12 -0
  437. package/dist/checks/resilience/reentrancy-guard.d.ts.map +1 -0
  438. package/dist/checks/resilience/reentrancy-guard.js +86 -0
  439. package/dist/checks/resilience/reentrancy-guard.js.map +1 -0
  440. package/dist/checks/resilience/retry-config-validation.d.ts +13 -0
  441. package/dist/checks/resilience/retry-config-validation.d.ts.map +1 -0
  442. package/dist/checks/resilience/retry-config-validation.js +159 -0
  443. package/dist/checks/resilience/retry-config-validation.js.map +1 -0
  444. package/dist/checks/resilience/sentry/_helpers/sentry.d.ts +25 -0
  445. package/dist/checks/resilience/sentry/_helpers/sentry.d.ts.map +1 -0
  446. package/dist/checks/resilience/sentry/_helpers/sentry.js +68 -0
  447. package/dist/checks/resilience/sentry/_helpers/sentry.js.map +1 -0
  448. package/dist/checks/resilience/sentry/index.d.ts +8 -0
  449. package/dist/checks/resilience/sentry/index.d.ts.map +1 -0
  450. package/dist/checks/resilience/sentry/index.js +8 -0
  451. package/dist/checks/resilience/sentry/index.js.map +1 -0
  452. package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts +12 -0
  453. package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts.map +1 -0
  454. package/dist/checks/resilience/sentry/sentry-dsn-configured.js +55 -0
  455. package/dist/checks/resilience/sentry/sentry-dsn-configured.js.map +1 -0
  456. package/dist/checks/resilience/sentry/sentry-environment-set.d.ts +12 -0
  457. package/dist/checks/resilience/sentry/sentry-environment-set.d.ts.map +1 -0
  458. package/dist/checks/resilience/sentry/sentry-environment-set.js +51 -0
  459. package/dist/checks/resilience/sentry/sentry-environment-set.js.map +1 -0
  460. package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts +12 -0
  461. package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts.map +1 -0
  462. package/dist/checks/resilience/sentry/sentry-error-boundary.js +75 -0
  463. package/dist/checks/resilience/sentry/sentry-error-boundary.js.map +1 -0
  464. package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts +13 -0
  465. package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts.map +1 -0
  466. package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js +125 -0
  467. package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js.map +1 -0
  468. package/dist/checks/resilience/sentry/sentry-release-set.d.ts +12 -0
  469. package/dist/checks/resilience/sentry/sentry-release-set.d.ts.map +1 -0
  470. package/dist/checks/resilience/sentry/sentry-release-set.js +51 -0
  471. package/dist/checks/resilience/sentry/sentry-release-set.js.map +1 -0
  472. package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts +12 -0
  473. package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts.map +1 -0
  474. package/dist/checks/resilience/sentry/sentry-sample-rate.js +78 -0
  475. package/dist/checks/resilience/sentry/sentry-sample-rate.js.map +1 -0
  476. package/dist/checks/resilience/sentry/sentry-source-maps.d.ts +12 -0
  477. package/dist/checks/resilience/sentry/sentry-source-maps.d.ts.map +1 -0
  478. package/dist/checks/resilience/sentry/sentry-source-maps.js +83 -0
  479. package/dist/checks/resilience/sentry/sentry-source-maps.js.map +1 -0
  480. package/dist/checks/resilience/service-patterns.d.ts +18 -0
  481. package/dist/checks/resilience/service-patterns.d.ts.map +1 -0
  482. package/dist/checks/resilience/service-patterns.js +230 -0
  483. package/dist/checks/resilience/service-patterns.js.map +1 -0
  484. package/dist/checks/resilience/timer-lifecycle.d.ts +10 -0
  485. package/dist/checks/resilience/timer-lifecycle.d.ts.map +1 -0
  486. package/dist/checks/resilience/timer-lifecycle.js +78 -0
  487. package/dist/checks/resilience/timer-lifecycle.js.map +1 -0
  488. package/dist/checks/resilience/transaction-patterns.d.ts +21 -0
  489. package/dist/checks/resilience/transaction-patterns.d.ts.map +1 -0
  490. package/dist/checks/resilience/transaction-patterns.js +258 -0
  491. package/dist/checks/resilience/transaction-patterns.js.map +1 -0
  492. package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts +9 -0
  493. package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts.map +1 -0
  494. package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js +37 -0
  495. package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js.map +1 -0
  496. package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts +2 -0
  497. package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts.map +1 -0
  498. package/dist/checks/security/__tests__/package-supply-chain-policy.test.js +128 -0
  499. package/dist/checks/security/__tests__/package-supply-chain-policy.test.js.map +1 -0
  500. package/dist/checks/security/api-key-rotation.d.ts +10 -0
  501. package/dist/checks/security/api-key-rotation.d.ts.map +1 -0
  502. package/dist/checks/security/api-key-rotation.js +186 -0
  503. package/dist/checks/security/api-key-rotation.js.map +1 -0
  504. package/dist/checks/security/auth-middleware-coverage.d.ts +11 -0
  505. package/dist/checks/security/auth-middleware-coverage.d.ts.map +1 -0
  506. package/dist/checks/security/auth-middleware-coverage.js +210 -0
  507. package/dist/checks/security/auth-middleware-coverage.js.map +1 -0
  508. package/dist/checks/security/auth-route-guard.d.ts +12 -0
  509. package/dist/checks/security/auth-route-guard.d.ts.map +1 -0
  510. package/dist/checks/security/auth-route-guard.js +70 -0
  511. package/dist/checks/security/auth-route-guard.js.map +1 -0
  512. package/dist/checks/security/cors-configuration.d.ts +11 -0
  513. package/dist/checks/security/cors-configuration.d.ts.map +1 -0
  514. package/dist/checks/security/cors-configuration.js +126 -0
  515. package/dist/checks/security/cors-configuration.js.map +1 -0
  516. package/dist/checks/security/csp-headers.d.ts +11 -0
  517. package/dist/checks/security/csp-headers.d.ts.map +1 -0
  518. package/dist/checks/security/csp-headers.js +192 -0
  519. package/dist/checks/security/csp-headers.js.map +1 -0
  520. package/dist/checks/security/dependency-vulnerability-audit.d.ts +15 -0
  521. package/dist/checks/security/dependency-vulnerability-audit.d.ts.map +1 -0
  522. package/dist/checks/security/dependency-vulnerability-audit.js +184 -0
  523. package/dist/checks/security/dependency-vulnerability-audit.js.map +1 -0
  524. package/dist/checks/security/env-secret-exposure.d.ts +11 -0
  525. package/dist/checks/security/env-secret-exposure.d.ts.map +1 -0
  526. package/dist/checks/security/env-secret-exposure.js +127 -0
  527. package/dist/checks/security/env-secret-exposure.js.map +1 -0
  528. package/dist/checks/security/hasura-production-config.d.ts +11 -0
  529. package/dist/checks/security/hasura-production-config.d.ts.map +1 -0
  530. package/dist/checks/security/hasura-production-config.js +122 -0
  531. package/dist/checks/security/hasura-production-config.js.map +1 -0
  532. package/dist/checks/security/index.d.ts +17 -0
  533. package/dist/checks/security/index.d.ts.map +1 -0
  534. package/dist/checks/security/index.js +17 -0
  535. package/dist/checks/security/index.js.map +1 -0
  536. package/dist/checks/security/jwt-validation.d.ts +11 -0
  537. package/dist/checks/security/jwt-validation.d.ts.map +1 -0
  538. package/dist/checks/security/jwt-validation.js +294 -0
  539. package/dist/checks/security/jwt-validation.js.map +1 -0
  540. package/dist/checks/security/no-eval.d.ts +16 -0
  541. package/dist/checks/security/no-eval.d.ts.map +1 -0
  542. package/dist/checks/security/no-eval.js +83 -0
  543. package/dist/checks/security/no-eval.js.map +1 -0
  544. package/dist/checks/security/no-hardcoded-secrets.d.ts +28 -0
  545. package/dist/checks/security/no-hardcoded-secrets.d.ts.map +1 -0
  546. package/dist/checks/security/no-hardcoded-secrets.js +209 -0
  547. package/dist/checks/security/no-hardcoded-secrets.js.map +1 -0
  548. package/dist/checks/security/package-supply-chain-policy.d.ts +12 -0
  549. package/dist/checks/security/package-supply-chain-policy.d.ts.map +1 -0
  550. package/dist/checks/security/package-supply-chain-policy.js +534 -0
  551. package/dist/checks/security/package-supply-chain-policy.js.map +1 -0
  552. package/dist/checks/security/rate-limit-coverage.d.ts +10 -0
  553. package/dist/checks/security/rate-limit-coverage.d.ts.map +1 -0
  554. package/dist/checks/security/rate-limit-coverage.js +143 -0
  555. package/dist/checks/security/rate-limit-coverage.js.map +1 -0
  556. package/dist/checks/security/semgrep-scan.d.ts +13 -0
  557. package/dist/checks/security/semgrep-scan.d.ts.map +1 -0
  558. package/dist/checks/security/semgrep-scan.js +86 -0
  559. package/dist/checks/security/semgrep-scan.js.map +1 -0
  560. package/dist/checks/security/use-centralized-crypto.d.ts +11 -0
  561. package/dist/checks/security/use-centralized-crypto.d.ts.map +1 -0
  562. package/dist/checks/security/use-centralized-crypto.js +129 -0
  563. package/dist/checks/security/use-centralized-crypto.js.map +1 -0
  564. package/dist/checks/security/webhook-signature-verification.d.ts +10 -0
  565. package/dist/checks/security/webhook-signature-verification.d.ts.map +1 -0
  566. package/dist/checks/security/webhook-signature-verification.js +183 -0
  567. package/dist/checks/security/webhook-signature-verification.js.map +1 -0
  568. package/dist/checks/testing/index.d.ts +6 -0
  569. package/dist/checks/testing/index.d.ts.map +1 -0
  570. package/dist/checks/testing/index.js +6 -0
  571. package/dist/checks/testing/index.js.map +1 -0
  572. package/dist/checks/testing/no-skipped-tests.d.ts +40 -0
  573. package/dist/checks/testing/no-skipped-tests.d.ts.map +1 -0
  574. package/dist/checks/testing/no-skipped-tests.js +174 -0
  575. package/dist/checks/testing/no-skipped-tests.js.map +1 -0
  576. package/dist/checks/testing/no-stub-tests.d.ts +11 -0
  577. package/dist/checks/testing/no-stub-tests.d.ts.map +1 -0
  578. package/dist/checks/testing/no-stub-tests.js +103 -0
  579. package/dist/checks/testing/no-stub-tests.js.map +1 -0
  580. package/dist/checks/testing/test-convention-consistency.d.ts +14 -0
  581. package/dist/checks/testing/test-convention-consistency.d.ts.map +1 -0
  582. package/dist/checks/testing/test-convention-consistency.js +93 -0
  583. package/dist/checks/testing/test-convention-consistency.js.map +1 -0
  584. package/dist/checks/testing/test-file-naming.d.ts +13 -0
  585. package/dist/checks/testing/test-file-naming.d.ts.map +1 -0
  586. package/dist/checks/testing/test-file-naming.js +218 -0
  587. package/dist/checks/testing/test-file-naming.js.map +1 -0
  588. package/dist/checks/testing/test-file-pairing.d.ts +13 -0
  589. package/dist/checks/testing/test-file-pairing.d.ts.map +1 -0
  590. package/dist/checks/testing/test-file-pairing.js +274 -0
  591. package/dist/checks/testing/test-file-pairing.js.map +1 -0
  592. package/dist/display/architecture.d.ts +9 -0
  593. package/dist/display/architecture.d.ts.map +1 -0
  594. package/dist/display/architecture.js +29 -0
  595. package/dist/display/architecture.js.map +1 -0
  596. package/dist/display/index.d.ts +20 -0
  597. package/dist/display/index.d.ts.map +1 -0
  598. package/dist/display/index.js +30 -0
  599. package/dist/display/index.js.map +1 -0
  600. package/dist/display/quality.d.ts +7 -0
  601. package/dist/display/quality.d.ts.map +1 -0
  602. package/dist/display/quality.js +34 -0
  603. package/dist/display/quality.js.map +1 -0
  604. package/dist/display/resilience.d.ts +7 -0
  605. package/dist/display/resilience.d.ts.map +1 -0
  606. package/dist/display/resilience.js +36 -0
  607. package/dist/display/resilience.js.map +1 -0
  608. package/dist/display/security-testing.d.ts +9 -0
  609. package/dist/display/security-testing.d.ts.map +1 -0
  610. package/dist/display/security-testing.js +31 -0
  611. package/dist/display/security-testing.js.map +1 -0
  612. package/dist/display/types.d.ts +6 -0
  613. package/dist/display/types.d.ts.map +1 -0
  614. package/dist/display/types.js +6 -0
  615. package/dist/display/types.js.map +1 -0
  616. package/dist/index.d.ts +19 -0
  617. package/dist/index.d.ts.map +1 -0
  618. package/dist/index.js +21 -0
  619. package/dist/index.js.map +1 -0
  620. package/package.json +52 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @fileoverview Validate routes have rate limiting configured
3
+ */
4
+ import { logger } from '@opensip-cli/core';
5
+ import { defineCheck } from '@opensip-cli/fitness';
6
+ import { stripStringLiterals, stripStringsAndComments } from '@opensip-cli/fitness';
7
+ /**
8
+ * Pre-compiled regex patterns for rate limit detection.
9
+ * These patterns match fixed, bounded strings with no user input - safe from ReDoS.
10
+ */
11
+ const RATE_LIMIT_REGEX = new RegExp('rateLimit|rateLimiter|preHandler.*rateLimit|onRequest.*rateLimit', 'i');
12
+ const INTERNAL_ROUTE_REGEX = new RegExp('/health|/metrics|/ready|/live|internal', 'i');
13
+ const FASTIFY_ROUTE_REGEX = new RegExp('fastify\\.(get|post|put|patch|delete)\\s*\\(\\s*[\'"`]/api[^\'"`]*[\'"`]', 'gi');
14
+ const EXPRESS_ROUTE_REGEX = new RegExp('(?:app|router)\\.(get|post|put|patch|delete)\\s*\\(\\s*[\'"`]/api[^\'"`]*[\'"`]', 'gi');
15
+ const SENSITIVE_ENDPOINT_REGEX = new RegExp('\\.(post|put)\\s*\\(\\s*[\'"`][^\'"`]*(?:login|signin|signup|register|password|reset|auth|token)[^\'"`]*[\'"`]', 'gi');
16
+ const GLOBAL_RATE_LIMIT_REGISTER_REGEX = new RegExp(String.raw `register\s*\(\s*(?:rateLimit|rateLimiter)`, 'i');
17
+ const GLOBAL_RATE_LIMIT_USE_REGEX = new RegExp(String.raw `use\s*\(\s*(?:rateLimit|rateLimiter)`, 'i');
18
+ const FRAMEWORK_DETECT_REGEX = /(?:fastify|app|router)\.(get|post|put|patch|delete)\s*\(/i;
19
+ /**
20
+ * Check if context has rate limiting
21
+ * @param context - The code context to check
22
+ * @returns True if rate limiting is present
23
+ */
24
+ function hasRateLimiting(context) {
25
+ logger.debug({
26
+ evt: 'fitness.checks.rate_limit_coverage.has_rate_limiting',
27
+ msg: 'Checking if context has rate limiting',
28
+ });
29
+ return RATE_LIMIT_REGEX.test(context);
30
+ }
31
+ /**
32
+ * Check if route is internal (health, metrics, etc.)
33
+ * @param context - The code context to check
34
+ * @returns True if the route is internal
35
+ */
36
+ function isInternalRoute(context) {
37
+ logger.debug({
38
+ evt: 'fitness.checks.rate_limit_coverage.is_internal_route',
39
+ msg: 'Checking if route is internal',
40
+ });
41
+ return INTERNAL_ROUTE_REGEX.test(context);
42
+ }
43
+ // Patterns that indicate route definitions needing rate limiting
44
+ const ROUTE_PATTERNS = [
45
+ // Fastify routes
46
+ {
47
+ regex: FASTIFY_ROUTE_REGEX,
48
+ check: (context) => !hasRateLimiting(context) && !isInternalRoute(context),
49
+ message: 'API route may be missing rate limiting configuration',
50
+ suggestion: 'Add rate limiting middleware: fastify.register(rateLimiter, { max: 100, timeWindow: "1 minute" }). Apply per-route or globally.',
51
+ severity: 'warning',
52
+ },
53
+ // Express routes
54
+ {
55
+ regex: EXPRESS_ROUTE_REGEX,
56
+ check: (context) => !hasRateLimiting(context) && !isInternalRoute(context),
57
+ message: 'API route may be missing rate limiting configuration',
58
+ suggestion: 'Add rate limiting middleware: app.use(rateLimiter({ max: 100, windowMs: 60000 })). Apply per-route or globally.',
59
+ severity: 'warning',
60
+ },
61
+ // Sensitive endpoints that must have rate limiting
62
+ {
63
+ regex: SENSITIVE_ENDPOINT_REGEX,
64
+ check: (context) => !hasRateLimiting(context),
65
+ message: 'Sensitive authentication endpoint should have rate limiting',
66
+ suggestion: 'Authentication endpoints must have strict rate limiting to prevent brute force attacks. Apply a limit of ~5-10 requests per minute for login/password endpoints.',
67
+ severity: 'error',
68
+ },
69
+ ];
70
+ /**
71
+ * Check: security/rate-limit-coverage
72
+ *
73
+ * Validates that routes have rate limiting configured.
74
+ */
75
+ export const rateLimitCoverage = defineCheck({
76
+ id: '19382a02-5d84-4316-b0a3-906f4acd7061',
77
+ slug: 'rate-limit-coverage',
78
+ disabled: true,
79
+ scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
80
+ contentFilter: 'strip-strings',
81
+ confidence: 'medium',
82
+ description: 'Validate routes have rate limiting configured',
83
+ longDescription: `**Purpose:** Ensures API routes have rate limiting configured to prevent abuse, with stricter enforcement on authentication endpoints.
84
+
85
+ **Detects:**
86
+ - Fastify routes (\`fastify.get/post/put/patch/delete('/api/...')\`) without rateLimit/rateLimiter in the surrounding context (next 8 lines)
87
+ - Express routes (\`app/router.get/post/put/patch/delete('/api/...')\`) without rate limiting
88
+ - Sensitive authentication endpoints (\`.post/.put\` with login, signin, signup, register, password, reset, auth, or token in path) missing rate limiting (elevated to error severity)
89
+
90
+ **Why it matters:** Without rate limiting, APIs are vulnerable to brute-force attacks, credential stuffing, and denial-of-service. Authentication endpoints are especially critical targets.
91
+
92
+ **Scope:** General best practice. Analyzes each file individually. Skips files with global rate limiting (\`register(rateLimit)\` or \`use(rateLimit)\`).`,
93
+ tags: ['security', 'rate-limiting', 'api'],
94
+ fileTypes: ['ts'],
95
+ analyze(content, filePath) {
96
+ logger.debug({
97
+ evt: 'fitness.checks.rate_limit_coverage.analyze',
98
+ msg: 'Analyzing file for rate limit coverage',
99
+ });
100
+ // Only check files that might define routes
101
+ if (!FRAMEWORK_DETECT_REGEX.test(stripStringsAndComments(content))) {
102
+ return [];
103
+ }
104
+ // Check if file has global rate limiting applied
105
+ const hasGlobalRateLimit = GLOBAL_RATE_LIMIT_REGISTER_REGEX.test(content) || GLOBAL_RATE_LIMIT_USE_REGEX.test(content);
106
+ // If global rate limiting is applied, skip detailed checking
107
+ if (hasGlobalRateLimit) {
108
+ return [];
109
+ }
110
+ const violations = [];
111
+ const lines = content.split('\n');
112
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
113
+ const line = lines[lineNum] ?? '';
114
+ // Get context (current line + next few lines)
115
+ const context = lines.slice(lineNum, lineNum + 8).join(' ');
116
+ // Skip comments
117
+ const trimmed = line.trim();
118
+ if (trimmed.startsWith('//') || trimmed.startsWith('*')) {
119
+ continue;
120
+ }
121
+ const strippedLine = stripStringLiterals(line);
122
+ const strippedContext = stripStringLiterals(context);
123
+ for (const pattern of ROUTE_PATTERNS) {
124
+ // Reset regex state
125
+ pattern.regex.lastIndex = 0;
126
+ const match = pattern.regex.exec(strippedLine);
127
+ if (match && pattern.check(strippedContext)) {
128
+ violations.push({
129
+ line: lineNum + 1,
130
+ column: match.index,
131
+ message: pattern.message,
132
+ severity: pattern.severity,
133
+ suggestion: pattern.suggestion,
134
+ match: match[0],
135
+ filePath,
136
+ });
137
+ }
138
+ }
139
+ }
140
+ return violations;
141
+ },
142
+ });
143
+ //# sourceMappingURL=rate-limit-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-coverage.js","sourceRoot":"","sources":["../../../src/checks/security/rate-limit-coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Semgrep static analysis security scan
3
+ *
4
+ * Runs Semgrep with auto config to detect security vulnerabilities,
5
+ * code injection, and other issues across all supported languages.
6
+ */
7
+ /**
8
+ * Check: security/semgrep-scan
9
+ *
10
+ * Runs Semgrep static analysis with curated security rules.
11
+ */
12
+ export declare const semgrepScan: import("@opensip-cli/fitness").Check;
13
+ //# sourceMappingURL=semgrep-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep-scan.d.ts","sourceRoot":"","sources":["../../../src/checks/security/semgrep-scan.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AA4FH;;;;GAIG;AACH,eAAO,MAAM,WAAW,sCA6BtB,CAAC"}
@@ -0,0 +1,86 @@
1
+ // @fitness-ignore-file batch-operation-limits -- reviewed: pattern is architecturally justified or false positive
2
+ /**
3
+ * @fileoverview Semgrep static analysis security scan
4
+ *
5
+ * Runs Semgrep with auto config to detect security vulnerabilities,
6
+ * code injection, and other issues across all supported languages.
7
+ */
8
+ import * as path from 'node:path';
9
+ import { defineCheck } from '@opensip-cli/fitness';
10
+ // =============================================================================
11
+ // SEVERITY MAPPING
12
+ // =============================================================================
13
+ /* v8 ignore start -- semgrep parsing helpers exercised via integration tests (requires semgrep CLI) */
14
+ function mapSeverity(semgrepSeverity) {
15
+ return semgrepSeverity === 'ERROR' ? 'error' : 'warning';
16
+ }
17
+ // =============================================================================
18
+ // OUTPUT PARSING
19
+ // =============================================================================
20
+ function parseSemgrepOutput(stdout, _stderr, _exitCode, _files, cwd) {
21
+ if (!stdout.trim())
22
+ return [];
23
+ let output;
24
+ try {
25
+ output = JSON.parse(stdout);
26
+ }
27
+ catch {
28
+ // @swallow-ok Non-JSON output from semgrep (e.g. login prompts, version warnings)
29
+ return [];
30
+ }
31
+ const violations = [];
32
+ for (const result of output.results) {
33
+ const meta = result.extra.metadata;
34
+ const cwe = meta?.cwe?.[0] ?? '';
35
+ const prefix = cwe ? `[${cwe.split(':')[0]}] ` : '';
36
+ violations.push({
37
+ filePath: path.isAbsolute(result.path) ? result.path : path.join(cwd, result.path),
38
+ line: result.start.line,
39
+ column: result.start.col,
40
+ message: `${prefix}${result.extra.message}`,
41
+ severity: mapSeverity(result.extra.severity),
42
+ suggestion: `Fix semgrep finding: ${result.check_id}`,
43
+ type: result.check_id,
44
+ match: result.check_id,
45
+ });
46
+ }
47
+ return violations;
48
+ }
49
+ /* v8 ignore stop */
50
+ // =============================================================================
51
+ // CHECK DEFINITION
52
+ // =============================================================================
53
+ /**
54
+ * Check: security/semgrep-scan
55
+ *
56
+ * Runs Semgrep static analysis with curated security rules.
57
+ */
58
+ export const semgrepScan = defineCheck({
59
+ id: 'b8e2f4a1-6c3d-4e5f-9a1b-7d8c2e3f4a5b',
60
+ slug: 'semgrep-scan',
61
+ scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
62
+ confidence: 'high',
63
+ description: 'Run Semgrep static analysis to detect security vulnerabilities',
64
+ longDescription: `**Purpose:** Runs Semgrep with \`--config auto\` to detect security vulnerabilities, injection flaws, and dangerous code patterns across the codebase.
65
+
66
+ **Detects:**
67
+ - Code injection (eval, template injection)
68
+ - SQL injection and command injection
69
+ - Insecure cryptographic usage
70
+ - Path traversal and SSRF
71
+ - Hardcoded secrets and credentials
72
+ - OWASP Top 10 vulnerability patterns
73
+
74
+ **Why it matters:** Semgrep performs AST-aware pattern matching that catches vulnerabilities regex-based tools miss. The \`auto\` config uses Semgrep's curated registry of security rules maintained by the community and Semgrep team.
75
+
76
+ **Requires:** \`semgrep\` CLI installed (\`pip install semgrep\` or \`brew install semgrep\`). 5-minute timeout for large codebases.`,
77
+ tags: ['security', 'static-analysis', 'vulnerability', 'owasp'],
78
+ timeout: 300_000, // 5 minutes — semgrep auto downloads rules on first run
79
+ command: {
80
+ bin: 'semgrep',
81
+ args: ['scan', '--json', '--config', 'auto', '--quiet', '.'],
82
+ expectedExitCodes: [0, 1], // 0 = clean, 1 = findings
83
+ parseOutput: parseSemgrepOutput,
84
+ },
85
+ });
86
+ //# sourceMappingURL=semgrep-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep-scan.js","sourceRoot":"","sources":["../../../src/checks/security/semgrep-scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Enforce use of centralized crypto module
3
+ */
4
+ /**
5
+ * Check: security/use-centralized-crypto
6
+ *
7
+ * Enforces that services use a centralized crypto utility instead of directly
8
+ * using Node.js crypto, AWS KMS SDK, or other crypto libraries.
9
+ */
10
+ export declare const useCentralizedCrypto: import("@opensip-cli/fitness").Check;
11
+ //# sourceMappingURL=use-centralized-crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-centralized-crypto.d.ts","sourceRoot":"","sources":["../../../src/checks/security/use-centralized-crypto.ts"],"names":[],"mappings":"AACA;;GAEG;AA8KH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,sCA8D/B,CAAC"}
@@ -0,0 +1,129 @@
1
+ // @fitness-ignore-file batch-operation-limits -- iterates bounded collections (config entries, registry items, or small analysis results)
2
+ /**
3
+ * @fileoverview Enforce use of centralized crypto module
4
+ */
5
+ import { logger } from '@opensip-cli/core';
6
+ import { createPathMatcher, defineCheck, isCommentLine, } from '@opensip-cli/fitness';
7
+ /**
8
+ * Creates a crypto pattern with standard RegExp
9
+ * Using RegExp constructor avoids sonarjs/regular-expr warnings on literal regex
10
+ * @param pattern - Pattern string to match
11
+ * @param message - Error message to display
12
+ * @param suggestion - Suggested fix
13
+ * @param severity - Severity level
14
+ * @returns Pattern configuration object
15
+ */
16
+ function createCryptoPattern(pattern, message, suggestion, severity) {
17
+ // @fitness-ignore-next-line semgrep-scan -- non-literal RegExp is intentional; patterns are hardcoded string constants for code analysis, not user input
18
+ return { regex: new RegExp(pattern, 'g'), message, suggestion, severity };
19
+ }
20
+ // Patterns indicating direct crypto usage
21
+ const DIRECT_CRYPTO_PATTERNS = [
22
+ // Node.js crypto module - symmetric/hashing
23
+ createCryptoPattern(String.raw `crypto\.createHash\s*\(`, 'Direct crypto.createHash usage - use hashingService.sha256() from crypto module', 'Use a centralized crypto utility instead of direct crypto.createHash calls.', 'error'),
24
+ createCryptoPattern(String.raw `crypto\.createHmac\s*\(`, 'Direct crypto.createHmac usage - use hashingService.hmac() from crypto module', 'Use a centralized crypto utility instead of direct crypto.createHmac calls.', 'error'),
25
+ createCryptoPattern(String.raw `crypto\.createCipheriv\s*\(`, 'Direct crypto.createCipheriv usage - use encryptionService.encrypt() from crypto module', 'Use a centralized crypto utility for encryption instead of direct crypto.createCipheriv calls.', 'error'),
26
+ createCryptoPattern(String.raw `crypto\.createDecipheriv\s*\(`, 'Direct crypto.createDecipheriv usage - use encryptionService.decrypt() from crypto module', 'Use a centralized crypto utility for decryption instead of direct crypto.createDecipheriv calls.', 'error'),
27
+ createCryptoPattern(String.raw `crypto\.pbkdf2(?:Sync)?\s*\(`, 'Direct crypto.pbkdf2 usage - use deriveKeyPbkdf2() from crypto module', 'Use a centralized crypto utility for key derivation instead of direct crypto.pbkdf2 calls.', 'error'),
28
+ createCryptoPattern(String.raw `crypto\.scrypt(?:Sync)?\s*\(`, 'Direct crypto.scrypt usage - use deriveKeyScrypt() from crypto module', 'Use a centralized crypto utility for key derivation instead of direct crypto.scrypt calls.', 'error'),
29
+ // Node.js crypto module - asymmetric signing
30
+ createCryptoPattern(String.raw `crypto\.createSign\s*\(`, 'Direct crypto.createSign usage - use signingService.sign() from crypto module', 'Use a centralized crypto utility for signing instead of direct crypto.createSign calls.', 'error'),
31
+ // @fitness-ignore-next-line jwt-validation -- Fitness check definition, not production code; .verify() in suggestion text
32
+ createCryptoPattern(String.raw `crypto\.createVerify\s*\(`, 'Direct crypto.createVerify usage - use signingService.verify() from crypto module', 'Use a centralized crypto utility for signature verification instead of direct crypto.createVerify calls.', 'error'),
33
+ createCryptoPattern(String.raw `crypto\.sign\s*\(`, 'Direct crypto.sign usage - use signingService.sign() from crypto module', 'Use a centralized crypto utility for signing instead of direct crypto.sign calls.', 'error'),
34
+ // @fitness-ignore-next-line jwt-validation -- Fitness check definition, not production code; .verify() in suggestion text
35
+ createCryptoPattern(String.raw `crypto\.verify\s*\(`, 'Direct crypto.verify usage - use signingService.verify() from crypto module', 'Use a centralized crypto utility for signature verification instead of direct crypto.verify calls.', 'error'),
36
+ // Direct createHmac import usage
37
+ createCryptoPattern(String.raw `\bcreateHmac\s*\(\s*['"]sha256['"]`, 'Direct createHmac usage - use hashingService.hmac() from crypto module', 'Use a centralized crypto utility instead of direct createHmac calls.', 'error'),
38
+ // AWS KMS direct imports
39
+ createCryptoPattern('@aws-sdk/client-kms', 'Direct AWS KMS SDK import - use a centralized crypto utility with KMS provider', 'Use a centralized crypto utility that handles KMS integration for key management.', 'error'),
40
+ createCryptoPattern(String.raw `new KMSClient\s*\(`, 'Direct KMSClient usage - use a centralized crypto utility with KMS provider', 'Use a centralized crypto utility that handles KMS integration for key management.', 'error'),
41
+ // bcrypt/argon2 direct imports
42
+ createCryptoPattern('from [\'"]bcrypt[\'"]', 'Direct bcrypt import - use hashingService.hashPassword() from crypto module', 'Use a centralized crypto utility for password hashing instead of direct bcrypt calls.', 'error'),
43
+ createCryptoPattern('from [\'"]argon2[\'"]', 'Direct argon2 import - use hashingService.hashPassword() from crypto module', 'Use a centralized crypto utility for password hashing instead of direct argon2 calls.', 'error'),
44
+ // Direct jose imports (should use ISigningService wrapper)
45
+ createCryptoPattern('from [\'"]jose[\'"]', 'Direct jose import - use ISigningService from crypto module', 'Use a centralized crypto utility for JWT operations instead of direct jose imports.', 'warning'),
46
+ createCryptoPattern(String.raw `import\s+\*\s+as\s+jose\s+from`, 'Direct jose import - use ISigningService from crypto module', 'Use a centralized crypto utility for JWT operations instead of direct jose imports.', 'warning'),
47
+ ];
48
+ // Paths to exclude from checking
49
+ const CRYPTO_IMPL_PATTERNS = [
50
+ // The crypto module itself (matches /infrastructure/src/crypto/)
51
+ '/crypto/adapters/',
52
+ '/crypto/core/',
53
+ '/crypto/interfaces/',
54
+ '/crypto/types/',
55
+ // Foundation modules may use crypto primitives
56
+ '/foundation/',
57
+ // Security JWT module uses jose for JWT-specific operations
58
+ '/security/implementations/jwt/',
59
+ // Cognito provider uses jose for AWS Cognito-specific JWT validation
60
+ '/security/providers/cognito/',
61
+ // Webhook verifiers implement provider-specific signature algorithms
62
+ '/webhooks/verifiers/',
63
+ // Fitness check definitions contain pattern strings, not actual crypto usage
64
+ '/fitness/src/checks/',
65
+ ];
66
+ const isExcludedCryptoPath = createPathMatcher(CRYPTO_IMPL_PATTERNS);
67
+ /**
68
+ * Check: security/use-centralized-crypto
69
+ *
70
+ * Enforces that services use a centralized crypto utility instead of directly
71
+ * using Node.js crypto, AWS KMS SDK, or other crypto libraries.
72
+ */
73
+ export const useCentralizedCrypto = defineCheck({
74
+ id: '38c350d5-1605-4d02-811c-c76261bcbba4',
75
+ slug: 'use-centralized-crypto',
76
+ disabled: true,
77
+ scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
78
+ contentFilter: 'strip-strings',
79
+ confidence: 'medium',
80
+ description: 'Enforce use of centralized crypto module instead of direct crypto operations',
81
+ longDescription: `**Purpose:** Enforces that services use a centralized crypto utility instead of directly calling Node.js crypto, AWS KMS, or third-party crypto libraries.
82
+
83
+ **Detects:**
84
+ - Direct Node.js crypto calls: \`crypto.createHash\`, \`crypto.createHmac\`, \`crypto.createCipheriv\`, \`crypto.createDecipheriv\`, \`crypto.pbkdf2\`, \`crypto.scrypt\`, \`crypto.createSign\`, \`crypto.createVerify\`, \`crypto.sign\`, \`crypto.verify\`
85
+ - Direct \`createHmac('sha256', ...)\` usage
86
+ - AWS KMS direct imports: \`@aws-sdk/client-kms\`, \`new KMSClient()\`
87
+ - Direct password hashing imports: \`from 'bcrypt'\`, \`from 'argon2'\`
88
+ - Direct JOSE imports: \`from 'jose'\`, \`import * as jose\`
89
+
90
+ **Why it matters:** Centralized crypto ensures consistent algorithm choices, key management, and makes it possible to audit or rotate cryptographic operations from a single location.
91
+
92
+ **Scope:** Codebase-specific convention. Analyzes each file individually. Excludes the crypto module itself, foundation, security JWT, Cognito provider, webhook verifiers, and fitness check definitions.`,
93
+ tags: ['security', 'crypto', 'centralization', 'best-practices'],
94
+ fileTypes: ['ts'],
95
+ analyze(content, filePath) {
96
+ logger.debug({
97
+ evt: 'fitness.checks.centralized_crypto.analyze',
98
+ msg: 'Analyzing file for direct crypto usage',
99
+ });
100
+ if (isExcludedCryptoPath(filePath)) {
101
+ return [];
102
+ }
103
+ const violations = [];
104
+ const lines = content.split('\n');
105
+ for (const [lineNum, line_] of lines.entries()) {
106
+ const line = line_ ?? '';
107
+ if (isCommentLine(line)) {
108
+ continue;
109
+ }
110
+ for (const pattern of DIRECT_CRYPTO_PATTERNS) {
111
+ pattern.regex.lastIndex = 0;
112
+ const match = pattern.regex.exec(line);
113
+ if (match) {
114
+ violations.push({
115
+ line: lineNum + 1,
116
+ column: match.index,
117
+ message: pattern.message,
118
+ severity: pattern.severity,
119
+ suggestion: pattern.suggestion,
120
+ match: match[0],
121
+ filePath,
122
+ });
123
+ }
124
+ }
125
+ }
126
+ return violations;
127
+ },
128
+ });
129
+ //# sourceMappingURL=use-centralized-crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-centralized-crypto.js","sourceRoot":"","sources":["../../../src/checks/security/use-centralized-crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Detect webhook endpoints without signature verification
3
+ */
4
+ /**
5
+ * Check: security/webhook-signature-verification
6
+ *
7
+ * Detects webhook endpoints without proper signature verification.
8
+ */
9
+ export declare const webhookSignatureVerification: import("@opensip-cli/fitness").Check;
10
+ //# sourceMappingURL=webhook-signature-verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-signature-verification.d.ts","sourceRoot":"","sources":["../../../src/checks/security/webhook-signature-verification.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiLH;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,sCAmDvC,CAAC"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @fileoverview Detect webhook endpoints without signature verification
3
+ */
4
+ import { logger } from '@opensip-cli/core';
5
+ import { defineCheck, isCommentLine } from '@opensip-cli/fitness';
6
+ /**
7
+ * Creates a security pattern with RegExp constructor
8
+ * Using RegExp constructor avoids sonarjs/regular-expr and sonarjs/slow-regex warnings
9
+ * @param options - The options for creating the pattern
10
+ * @returns Security pattern configuration
11
+ */
12
+ function createSecurityPattern(options) {
13
+ const { pattern, flags, message, suggestion, severity, category } = options;
14
+ // @fitness-ignore-next-line semgrep-scan -- non-literal RegExp is intentional; patterns are hardcoded string constants for code analysis, not user input
15
+ return { regex: new RegExp(pattern, flags), message, suggestion, severity, category };
16
+ }
17
+ /**
18
+ * Check if a file path is a webhook-related file
19
+ * @param filePath - Path to check
20
+ * @returns True if file is webhook-related
21
+ */
22
+ function isWebhookRelatedFile(filePath) {
23
+ logger.debug({
24
+ evt: 'fitness.checks.webhook_signature.is_webhook_related_file',
25
+ msg: 'Checking if file is webhook-related',
26
+ });
27
+ const lowerPath = filePath.toLowerCase();
28
+ // Simple checks that are safe from ReDoS
29
+ if (lowerPath.includes('webhook')) {
30
+ return true;
31
+ }
32
+ // Check for /hook/ or /hooks/ path segments
33
+ return lowerPath.includes('/hook/') || lowerPath.includes('/hooks/');
34
+ }
35
+ // Patterns indicating proper verifier usage - simple string checks
36
+ const VERIFIER_STRINGS = [
37
+ 'infrastructure/webhooks',
38
+ 'createHmacVerifier',
39
+ 'createStripeVerifier',
40
+ 'createTwilioVerifier',
41
+ 'createSendGridVerifier',
42
+ 'verifySignature',
43
+ 'validateSignature',
44
+ ];
45
+ /**
46
+ * Check if content has proper verifier imports
47
+ * @param content - File content
48
+ * @returns True if content has verifier imports
49
+ */
50
+ function hasVerifierImport(content) {
51
+ logger.debug({
52
+ evt: 'fitness.checks.webhook_signature.has_verifier_import',
53
+ msg: 'Checking if content has verifier imports',
54
+ });
55
+ return VERIFIER_STRINGS.some((str) => content.includes(str));
56
+ }
57
+ // Security issue patterns - using RegExp constructor to avoid sonarjs warnings
58
+ const SECURITY_ISSUE_PATTERNS = [
59
+ // Hardcoded webhook secrets - simplified non-backtracking pattern
60
+ createSecurityPattern({
61
+ pattern: String.raw `(?:webhook)?secret\s*[:=]\s*['"][^'"]{10,}['"]`,
62
+ flags: 'gi',
63
+ message: 'Hardcoded webhook secret detected - use environment variables',
64
+ suggestion: 'Move webhook secret to environment variable: process.env.WEBHOOK_SECRET. Never commit secrets to source control.',
65
+ severity: 'error',
66
+ category: 'hardcoded-secret',
67
+ }),
68
+ createSecurityPattern({
69
+ pattern: 'whsec_[a-zA-Z0-9]+',
70
+ flags: 'g',
71
+ message: 'Hardcoded Stripe webhook secret detected - use environment variables',
72
+ suggestion: 'Move Stripe webhook secret to process.env.STRIPE_WEBHOOK_SECRET. Rotate the secret immediately if it was exposed in git history.',
73
+ severity: 'error',
74
+ category: 'hardcoded-secret',
75
+ }),
76
+ // Direct string comparison for signatures (not timing-safe)
77
+ // Simplified pattern without lookahead to avoid slow-regex/backtracking
78
+ createSecurityPattern({
79
+ pattern: String.raw `signature\s*(?:===|!==|==|!=)\s*[^;]+`,
80
+ flags: 'gi',
81
+ message: 'Direct signature comparison detected - use timing-safe comparison to prevent timing attacks',
82
+ suggestion: 'Use crypto.timingSafeEqual() for signature comparison: crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)). Direct comparison is vulnerable to timing attacks.',
83
+ severity: 'warning',
84
+ category: 'insecure-signature',
85
+ }),
86
+ ];
87
+ // Patterns indicating JSON parsing without verification - simplified
88
+ const UNSAFE_JSON_PATTERNS = [
89
+ createSecurityPattern({
90
+ pattern: String.raw `JSON\.parse\s*\([^)]*(?:req\.body|request\.body|rawBody)`,
91
+ flags: 'gi',
92
+ message: 'JSON.parse on webhook body without signature verification - use a shared webhook verification utility',
93
+ suggestion: 'Use webhook verifiers that handle signature verification. Example: const payload = await verifier.verify(req);',
94
+ severity: 'error',
95
+ category: 'missing-verification',
96
+ }),
97
+ ];
98
+ /**
99
+ * Check if file should be skipped
100
+ * @param filePath - Path to check
101
+ * @returns True if file should be skipped
102
+ */
103
+ function shouldSkipFile(filePath) {
104
+ logger.debug({
105
+ evt: 'fitness.checks.webhook_signature.should_skip_file',
106
+ msg: 'Checking if file should be skipped',
107
+ });
108
+ return !isWebhookRelatedFile(filePath);
109
+ }
110
+ function checkPatterns(patterns, line, lineNum, filePath) {
111
+ logger.debug({
112
+ evt: 'fitness.checks.webhook_signature.check_patterns',
113
+ msg: 'Checking line against security patterns',
114
+ });
115
+ const violations = [];
116
+ for (const pattern of patterns) {
117
+ pattern.regex.lastIndex = 0;
118
+ const match = pattern.regex.exec(line);
119
+ if (match) {
120
+ violations.push({
121
+ line: lineNum + 1,
122
+ column: match.index,
123
+ message: pattern.message,
124
+ severity: pattern.severity,
125
+ suggestion: pattern.suggestion,
126
+ match: match[0],
127
+ type: pattern.category,
128
+ filePath,
129
+ });
130
+ }
131
+ }
132
+ return violations;
133
+ }
134
+ /**
135
+ * Check: security/webhook-signature-verification
136
+ *
137
+ * Detects webhook endpoints without proper signature verification.
138
+ */
139
+ export const webhookSignatureVerification = defineCheck({
140
+ id: '02a157b3-88a9-45d4-95da-ed754e347439',
141
+ slug: 'webhook-signature-verification',
142
+ disabled: true,
143
+ tags: ['security'],
144
+ scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
145
+ contentFilter: 'strip-strings',
146
+ confidence: 'medium',
147
+ description: 'Detect webhook endpoints without signature verification',
148
+ longDescription: `**Purpose:** Detects webhook handler files that process incoming payloads without proper signature verification, and flags related security issues.
149
+
150
+ **Detects:**
151
+ - Hardcoded webhook secrets: \`secret: '<value>'\` or \`whsec_\` prefixed Stripe webhook secrets in source code
152
+ - Direct signature string comparison using \`===\`/\`!==\`/\`==\`/\`!=\` (vulnerable to timing attacks)
153
+ - \`JSON.parse(req.body)\` / \`JSON.parse(request.body)\` / \`JSON.parse(rawBody)\` in webhook files without verifier imports (infrastructure/webhooks, createHmacVerifier, createStripeVerifier, etc.)
154
+
155
+ **Why it matters:** Without signature verification, attackers can forge webhook payloads to trigger unauthorized actions. Direct string comparison of signatures leaks timing information.
156
+
157
+ **Scope:** General best practice. Analyzes each file individually. Only scans files in webhook/hook-related paths.`,
158
+ fileTypes: ['ts'],
159
+ analyze(content, filePath) {
160
+ logger.debug({
161
+ evt: 'fitness.checks.webhook_signature.analyze',
162
+ msg: 'Analyzing file for webhook signature verification',
163
+ });
164
+ if (shouldSkipFile(filePath)) {
165
+ return [];
166
+ }
167
+ const violations = [];
168
+ const fileHasVerifierImport = hasVerifierImport(content);
169
+ const lines = content.split('\n');
170
+ for (const [lineNum, line_] of lines.entries()) {
171
+ const line = line_ ?? '';
172
+ if (isCommentLine(line)) {
173
+ continue;
174
+ }
175
+ violations.push(...checkPatterns(SECURITY_ISSUE_PATTERNS, line, lineNum, filePath));
176
+ if (!fileHasVerifierImport) {
177
+ violations.push(...checkPatterns(UNSAFE_JSON_PATTERNS, line, lineNum, filePath));
178
+ }
179
+ }
180
+ return violations;
181
+ },
182
+ });
183
+ //# sourceMappingURL=webhook-signature-verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-signature-verification.js","sourceRoot":"","sources":["../../../src/checks/security/webhook-signature-verification.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAuB,MAAM,sBAAsB,CAAC;AAyBvF;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,OAAqC;IAClE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC5E,yJAAyJ;IACzJ,OAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACxF,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,QAAgB;IAC5C,MAAM,CAAC,KAAK,CAAC;QACX,GAAG,EAAE,0DAA0D;QAC/D,GAAG,EAAE,qCAAqC;KAC3C,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACzC,yCAAyC;IACzC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,4CAA4C;IAC5C,OAAO,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACvE,CAAC;AAED,mEAAmE;AACnE,MAAM,gBAAgB,GAAG;IACvB,yBAAyB;IACzB,oBAAoB;IACpB,sBAAsB;IACtB,sBAAsB;IACtB,wBAAwB;IACxB,iBAAiB;IACjB,mBAAmB;CACpB,CAAC;AAEF;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,CAAC,KAAK,CAAC;QACX,GAAG,EAAE,sDAAsD;QAC3D,GAAG,EAAE,0CAA0C;KAChD,CAAC,CAAC;IACH,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,+EAA+E;AAC/E,MAAM,uBAAuB,GAAsB;IACjD,kEAAkE;IAClE,qBAAqB,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAA,gDAAgD;QACnE,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,+DAA+D;QACxE,UAAU,EACR,kHAAkH;QACpH,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,qBAAqB,CAAC;QACpB,OAAO,EAAE,oBAAoB;QAC7B,KAAK,EAAE,GAAG;QACV,OAAO,EAAE,sEAAsE;QAC/E,UAAU,EACR,kIAAkI;QACpI,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,4DAA4D;IAC5D,wEAAwE;IACxE,qBAAqB,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAA,uCAAuC;QAC1D,KAAK,EAAE,IAAI;QACX,OAAO,EACL,6FAA6F;QAC/F,UAAU,EACR,mKAAmK;QACrK,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,oBAAoB;KAC/B,CAAC;CACH,CAAC;AAEF,qEAAqE;AACrE,MAAM,oBAAoB,GAAsB;IAC9C,qBAAqB,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAA,0DAA0D;QAC7E,KAAK,EAAE,IAAI;QACX,OAAO,EACL,uGAAuG;QACzG,UAAU,EACR,gHAAgH;QAClH,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,sBAAsB;KACjC,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,CAAC,KAAK,CAAC;QACX,GAAG,EAAE,mDAAmD;QACxD,GAAG,EAAE,oCAAoC;KAC1C,CAAC,CAAC;IACH,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,aAAa,CACpB,QAA2B,EAC3B,IAAY,EACZ,OAAe,EACf,QAAgB;IAEhB,MAAM,CAAC,KAAK,CAAC;QACX,GAAG,EAAE,iDAAiD;QACtD,GAAG,EAAE,yCAAyC;KAC/C,CAAC,CAAC;IACH,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,OAAO,GAAG,CAAC;gBACjB,MAAM,EAAE,KAAK,CAAC,KAAK;gBACnB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACf,IAAI,EAAE,OAAO,CAAC,QAAQ;gBACtB,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CAAC;IACtD,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,gCAAgC;IACtC,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE;IACrE,aAAa,EAAE,eAAe;IAE9B,UAAU,EAAE,QAAQ;IACpB,WAAW,EAAE,yDAAyD;IACtE,eAAe,EAAE;;;;;;;;;mHASgG;IACjH,SAAS,EAAE,CAAC,IAAI,CAAC;IAEjB,OAAO,CAAC,OAAe,EAAE,QAAgB;QACvC,MAAM,CAAC,KAAK,CAAC;YACX,GAAG,EAAE,0CAA0C;YAC/C,GAAG,EAAE,mDAAmD;SACzD,CAAC,CAAC;QACH,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,UAAU,GAAqB,EAAE,CAAC;QACxC,MAAM,qBAAqB,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAEzB,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,SAAS;YACX,CAAC;YAED,UAAU,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;YAEpF,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,UAAU,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,oBAAoB,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './no-skipped-tests.js';
2
+ export * from './no-stub-tests.js';
3
+ export * from './test-convention-consistency.js';
4
+ export * from './test-file-naming.js';
5
+ export * from './test-file-pairing.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/checks/testing/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kCAAkC,CAAC;AACjD,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}