@howlil/ez-agents 3.4.2 → 4.0.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 (365) hide show
  1. package/README.md +735 -462
  2. package/agents/ez-architect-agent.md +267 -0
  3. package/agents/ez-backend-agent.md +303 -0
  4. package/agents/ez-chief-strategist.md +271 -0
  5. package/agents/ez-codebase-mapper.md +770 -770
  6. package/agents/ez-context-manager.md +319 -0
  7. package/agents/ez-debugger.md +1255 -1255
  8. package/agents/ez-design-expert.md +347 -0
  9. package/agents/ez-devops-agent.md +331 -0
  10. package/agents/ez-executor.md +487 -487
  11. package/agents/ez-frontend-agent.md +322 -0
  12. package/agents/ez-phase-researcher.md +553 -553
  13. package/agents/ez-planner.md +1307 -1307
  14. package/agents/ez-product-engineer.md +435 -0
  15. package/agents/ez-project-researcher.md +629 -629
  16. package/agents/ez-qa-agent.md +320 -0
  17. package/agents/ez-release-agent.md +333 -0
  18. package/agents/ez-requirements-agent.md +377 -0
  19. package/agents/ez-roadmapper.md +650 -650
  20. package/agents/ez-technical-writer.md +551 -0
  21. package/agents/ez-ux-expert.md +393 -0
  22. package/agents/ez-verifier.md +579 -579
  23. package/bin/guards/autonomy-guard.cjs +346 -0
  24. package/bin/guards/context-budget-guard.cjs +278 -0
  25. package/bin/guards/hallucination-guard.cjs +380 -0
  26. package/bin/guards/hidden-state-guard.cjs +182 -0
  27. package/bin/guards/team-overhead-guard.cjs +266 -0
  28. package/bin/guards/tool-sprawl-guard.cjs +271 -0
  29. package/bin/install.js +3221 -3272
  30. package/bin/lib/analytics/analytics-collector.cjs +86 -0
  31. package/bin/lib/analytics/analytics-reporter.cjs +130 -0
  32. package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
  33. package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
  34. package/bin/lib/analytics/nps-tracker.cjs +147 -0
  35. package/bin/lib/archetype-detector.cjs +289 -0
  36. package/bin/lib/assistant-adapter.cjs +361 -0
  37. package/bin/lib/audit-exec.cjs +175 -0
  38. package/bin/lib/auth.cjs +176 -0
  39. package/bin/lib/backup-service.cjs +422 -0
  40. package/bin/lib/bdd-validator.cjs +622 -0
  41. package/bin/lib/business-flow-mapper.cjs +429 -0
  42. package/bin/lib/circuit-breaker.cjs +276 -0
  43. package/bin/lib/code-complexity-analyzer.cjs +360 -0
  44. package/bin/lib/codebase-analyzer.cjs +241 -0
  45. package/bin/lib/commands.cjs +691 -0
  46. package/bin/lib/config.cjs +236 -0
  47. package/bin/lib/constraint-extractor.cjs +526 -0
  48. package/bin/lib/content-scanner.cjs +238 -0
  49. package/bin/lib/context-cache.cjs +154 -0
  50. package/bin/lib/context-compressor.cjs +102 -0
  51. package/bin/lib/context-deduplicator.cjs +105 -0
  52. package/bin/lib/context-errors.cjs +78 -0
  53. package/bin/lib/context-manager.cjs +338 -0
  54. package/bin/lib/context-metadata-tracker.cjs +140 -0
  55. package/bin/lib/context-relevance-scorer.cjs +99 -0
  56. package/bin/lib/core.cjs +507 -0
  57. package/bin/lib/cost-alerts.cjs +174 -0
  58. package/bin/lib/cost-tracker.cjs +275 -0
  59. package/bin/lib/crash-recovery.cjs +220 -0
  60. package/bin/lib/dependency-graph.cjs +319 -0
  61. package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
  62. package/bin/lib/deploy/deploy-detector.cjs +69 -0
  63. package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
  64. package/bin/lib/deploy/deploy-health-check.cjs +88 -0
  65. package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
  66. package/bin/lib/deploy/deploy-rollback.cjs +72 -0
  67. package/bin/lib/deploy/deploy-runner.cjs +97 -0
  68. package/bin/lib/deploy/deploy-status.cjs +74 -0
  69. package/bin/lib/discussion-synthesizer.cjs +439 -0
  70. package/bin/lib/error-cache.cjs +114 -0
  71. package/bin/lib/error-registry.cjs +177 -0
  72. package/bin/lib/file-access.cjs +207 -0
  73. package/bin/lib/file-lock.cjs +236 -0
  74. package/bin/lib/finops/budget-enforcer.cjs +126 -0
  75. package/bin/lib/finops/cost-reporter.cjs +132 -0
  76. package/bin/lib/finops/finops-analyzer.cjs +112 -0
  77. package/bin/lib/finops/spot-manager.cjs +118 -0
  78. package/bin/lib/framework-detector.cjs +396 -0
  79. package/bin/lib/frontmatter.cjs +313 -0
  80. package/bin/lib/fs-utils.cjs +153 -0
  81. package/bin/lib/gate-executor.cjs +272 -0
  82. package/bin/lib/gates/README.md +374 -0
  83. package/bin/lib/gates/gate-01-requirement.cjs +303 -0
  84. package/bin/lib/gates/gate-02-architecture.cjs +555 -0
  85. package/bin/lib/gates/gate-03-code.cjs +635 -0
  86. package/bin/lib/gates/gate-04-security.cjs +829 -0
  87. package/bin/lib/git-errors.cjs +83 -0
  88. package/bin/lib/git-utils.cjs +321 -0
  89. package/bin/lib/git-workflow-engine.cjs +1157 -0
  90. package/bin/lib/health-check.cjs +227 -0
  91. package/bin/lib/index.cjs +279 -0
  92. package/bin/lib/init.cjs +725 -0
  93. package/bin/lib/lock-logger.cjs +194 -0
  94. package/bin/lib/lock-state.cjs +263 -0
  95. package/bin/lib/lockfile-validator.cjs +227 -0
  96. package/bin/lib/log-rotation.cjs +71 -0
  97. package/bin/lib/logger.cjs +125 -0
  98. package/bin/lib/memory-compression.cjs +256 -0
  99. package/bin/lib/milestone.cjs +247 -0
  100. package/bin/lib/model-provider.cjs +241 -0
  101. package/bin/lib/package-manager-detector.cjs +203 -0
  102. package/bin/lib/package-manager-executor.cjs +385 -0
  103. package/bin/lib/package-manager-service.cjs +216 -0
  104. package/bin/lib/perf/api-monitor.cjs +88 -0
  105. package/bin/lib/perf/db-optimizer.cjs +78 -0
  106. package/bin/lib/perf/frontend-performance.cjs +56 -0
  107. package/bin/lib/perf/perf-analyzer.cjs +77 -0
  108. package/bin/lib/perf/perf-baseline.cjs +102 -0
  109. package/bin/lib/perf/perf-reporter.cjs +117 -0
  110. package/bin/lib/perf/regression-detector.cjs +92 -0
  111. package/bin/lib/phase.cjs +963 -0
  112. package/bin/lib/planning-write.cjs +123 -0
  113. package/bin/lib/project-reporter.cjs +565 -0
  114. package/bin/lib/quality-gate.cjs +332 -0
  115. package/bin/lib/quality-metrics.cjs +324 -0
  116. package/bin/lib/recovery-manager.cjs +98 -0
  117. package/bin/lib/release-validator.cjs +617 -0
  118. package/bin/lib/retry.cjs +119 -0
  119. package/bin/lib/roadmap.cjs +309 -0
  120. package/bin/lib/safe-exec.cjs +173 -0
  121. package/bin/lib/safe-path.cjs +130 -0
  122. package/bin/lib/security-errors.cjs +62 -0
  123. package/bin/lib/session-chain.cjs +304 -0
  124. package/bin/lib/session-errors.cjs +81 -0
  125. package/bin/lib/session-export.cjs +251 -0
  126. package/bin/lib/session-import.cjs +262 -0
  127. package/bin/lib/session-manager.cjs +280 -0
  128. package/bin/lib/skill-context.cjs +148 -0
  129. package/bin/lib/skill-matcher.cjs +236 -0
  130. package/bin/lib/skill-registry.cjs +360 -0
  131. package/bin/lib/skill-resolver.cjs +449 -0
  132. package/bin/lib/skill-triggers.cjs +90 -0
  133. package/bin/lib/skill-validator.cjs +270 -0
  134. package/bin/lib/skill-versioning.cjs +355 -0
  135. package/bin/lib/stack-detector.cjs +399 -0
  136. package/bin/lib/state.cjs +736 -0
  137. package/bin/lib/tech-debt-analyzer.cjs +309 -0
  138. package/bin/lib/temp-file.cjs +239 -0
  139. package/bin/lib/template.cjs +223 -0
  140. package/bin/lib/test-file-lock.cjs +112 -0
  141. package/bin/lib/test-graceful.cjs +93 -0
  142. package/bin/lib/test-logger.cjs +60 -0
  143. package/bin/lib/test-safe-exec.cjs +38 -0
  144. package/bin/lib/test-safe-path.cjs +33 -0
  145. package/bin/lib/test-temp-file.cjs +125 -0
  146. package/bin/lib/tier-manager.cjs +428 -0
  147. package/bin/lib/timeout-exec.cjs +63 -0
  148. package/bin/lib/tradeoff-analyzer.cjs +284 -0
  149. package/bin/lib/url-fetch.cjs +170 -0
  150. package/bin/lib/verify.cjs +863 -0
  151. package/bin/update.js +217 -214
  152. package/commands/deploy.cjs +53 -0
  153. package/commands/ez/add-tests.md +41 -41
  154. package/commands/ez/audit-milestone.md +36 -36
  155. package/commands/ez/complete-milestone.md +136 -136
  156. package/commands/ez/discuss-phase.md +90 -90
  157. package/commands/ez/execute-phase.md +52 -41
  158. package/commands/ez/help.md +22 -22
  159. package/commands/ez/map-codebase.md +71 -71
  160. package/commands/ez/new-milestone.md +44 -44
  161. package/commands/ez/new-project.md +51 -42
  162. package/commands/ez/plan-phase.md +53 -45
  163. package/commands/ez/progress.md +36 -24
  164. package/commands/ez/quick.md +45 -45
  165. package/commands/ez/resume-work.md +40 -40
  166. package/commands/ez/run-phase.md +580 -0
  167. package/commands/ez/settings.md +36 -36
  168. package/commands/ez/update.md +37 -37
  169. package/commands/ez/verify-work.md +402 -38
  170. package/commands/health-check.cjs +44 -0
  171. package/commands/rollback.cjs +47 -0
  172. package/ez-agents/bin/ez-tools.cjs +1692 -716
  173. package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
  174. package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
  175. package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
  176. package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
  177. package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
  178. package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
  179. package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
  180. package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
  181. package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
  182. package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
  183. package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
  184. package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
  185. package/ez-agents/bin/lib/audit-exec.cjs +166 -167
  186. package/ez-agents/bin/lib/auth.cjs +176 -176
  187. package/ez-agents/bin/lib/backup-service.cjs +422 -0
  188. package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
  189. package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
  190. package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
  191. package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
  192. package/ez-agents/bin/lib/commands.cjs +685 -685
  193. package/ez-agents/bin/lib/config.cjs +41 -1
  194. package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
  195. package/ez-agents/bin/lib/content-scanner.cjs +238 -0
  196. package/ez-agents/bin/lib/context-cache.cjs +154 -0
  197. package/ez-agents/bin/lib/context-errors.cjs +71 -0
  198. package/ez-agents/bin/lib/context-manager.cjs +220 -0
  199. package/ez-agents/bin/lib/core.cjs +507 -512
  200. package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
  201. package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
  202. package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
  203. package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
  204. package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
  205. package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
  206. package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
  207. package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
  208. package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
  209. package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
  210. package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
  211. package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
  212. package/ez-agents/bin/lib/file-access.cjs +207 -0
  213. package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
  214. package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
  215. package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
  216. package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
  217. package/ez-agents/bin/lib/framework-detector.cjs +396 -0
  218. package/ez-agents/bin/lib/frontmatter.cjs +3 -1
  219. package/ez-agents/bin/lib/gates/README.md +374 -0
  220. package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
  221. package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
  222. package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
  223. package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
  224. package/ez-agents/bin/lib/git-errors.cjs +83 -0
  225. package/ez-agents/bin/lib/git-utils.cjs +118 -0
  226. package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
  227. package/ez-agents/bin/lib/health-check.cjs +162 -162
  228. package/ez-agents/bin/lib/index.cjs +40 -2
  229. package/ez-agents/bin/lib/init.cjs +0 -2
  230. package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
  231. package/ez-agents/bin/lib/log-rotation.cjs +71 -0
  232. package/ez-agents/bin/lib/logger.cjs +99 -154
  233. package/ez-agents/bin/lib/memory-compression.cjs +256 -0
  234. package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
  235. package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
  236. package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
  237. package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
  238. package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
  239. package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
  240. package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
  241. package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
  242. package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
  243. package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
  244. package/ez-agents/bin/lib/project-reporter.cjs +502 -0
  245. package/ez-agents/bin/lib/quality-gate.cjs +332 -0
  246. package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
  247. package/ez-agents/bin/lib/release-validator.cjs +617 -0
  248. package/ez-agents/bin/lib/safe-exec.cjs +128 -214
  249. package/ez-agents/bin/lib/security-errors.cjs +62 -0
  250. package/ez-agents/bin/lib/session-chain.cjs +304 -0
  251. package/ez-agents/bin/lib/session-errors.cjs +81 -0
  252. package/ez-agents/bin/lib/session-export.cjs +251 -0
  253. package/ez-agents/bin/lib/session-import.cjs +262 -0
  254. package/ez-agents/bin/lib/session-manager.cjs +280 -0
  255. package/ez-agents/bin/lib/skill-context.cjs +148 -0
  256. package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
  257. package/ez-agents/bin/lib/skill-registry.cjs +341 -0
  258. package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
  259. package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
  260. package/ez-agents/bin/lib/skill-validator.cjs +270 -0
  261. package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
  262. package/ez-agents/bin/lib/stack-detector.cjs +399 -0
  263. package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
  264. package/ez-agents/bin/lib/tier-manager.cjs +428 -0
  265. package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
  266. package/ez-agents/bin/lib/url-fetch.cjs +170 -0
  267. package/ez-agents/bin/lib/verify.cjs +863 -863
  268. package/ez-agents/references/decimal-phase-calculation.md +65 -65
  269. package/ez-agents/references/git-integration.md +248 -248
  270. package/ez-agents/references/git-planning-commit.md +38 -38
  271. package/ez-agents/references/metrics-schema.md +118 -0
  272. package/ez-agents/references/model-profile-resolution.md +34 -34
  273. package/ez-agents/references/model-profiles.md +93 -93
  274. package/ez-agents/references/phase-argument-parsing.md +61 -61
  275. package/ez-agents/references/planning-config.md +340 -200
  276. package/ez-agents/references/tier-strategy.md +103 -0
  277. package/ez-agents/references/ui-brand.md +160 -160
  278. package/ez-agents/references/verification-patterns.md +612 -612
  279. package/ez-agents/templates/DEBUG.md +164 -164
  280. package/ez-agents/templates/UAT.md +247 -247
  281. package/ez-agents/templates/agent-output-format.md +404 -0
  282. package/ez-agents/templates/bdd-feature.md +173 -0
  283. package/ez-agents/templates/codebase/architecture.md +255 -255
  284. package/ez-agents/templates/codebase/structure.md +285 -285
  285. package/ez-agents/templates/copilot-instructions.md +7 -7
  286. package/ez-agents/templates/debug-subagent-prompt.md +91 -91
  287. package/ez-agents/templates/discovery.md +146 -146
  288. package/ez-agents/templates/discussion.md +68 -0
  289. package/ez-agents/templates/handoff-protocol.md +294 -0
  290. package/ez-agents/templates/incident-runbook.md +205 -0
  291. package/ez-agents/templates/mode-workflow-templates.md +301 -0
  292. package/ez-agents/templates/phase-prompt.md +610 -610
  293. package/ez-agents/templates/planner-subagent-prompt.md +117 -117
  294. package/ez-agents/templates/project.md +184 -184
  295. package/ez-agents/templates/release-checklist.md +136 -0
  296. package/ez-agents/templates/research.md +552 -552
  297. package/ez-agents/templates/rollback-plan.md +201 -0
  298. package/ez-agents/templates/security-user-setup.md +244 -0
  299. package/ez-agents/templates/skill-validation-rules.md +476 -0
  300. package/ez-agents/templates/state.md +180 -176
  301. package/ez-agents/templates/summary-complex.md +59 -59
  302. package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
  303. package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
  304. package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
  305. package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
  306. package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
  307. package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
  308. package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
  309. package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
  310. package/ez-agents/workflows/audit-milestone.md +1 -1
  311. package/ez-agents/workflows/autonomous.md +131 -30
  312. package/ez-agents/workflows/complete-milestone.md +1 -1
  313. package/ez-agents/workflows/discuss-phase.md +1 -1
  314. package/ez-agents/workflows/execute-phase.md +169 -3
  315. package/ez-agents/workflows/help.md +86 -133
  316. package/ez-agents/workflows/hotfix.md +291 -0
  317. package/ez-agents/workflows/new-milestone.md +340 -11
  318. package/ez-agents/workflows/new-project.md +294 -318
  319. package/ez-agents/workflows/plan-phase.md +22 -40
  320. package/ez-agents/workflows/progress.md +15 -25
  321. package/ez-agents/workflows/release.md +253 -0
  322. package/ez-agents/workflows/resume-session.md +215 -0
  323. package/ez-agents/workflows/run-phase.md +531 -0
  324. package/ez-agents/workflows/settings.md +2 -35
  325. package/hooks/dist/ez-check-update.js +81 -81
  326. package/hooks/dist/ez-context-monitor.js +148 -141
  327. package/hooks/dist/ez-statusline.js +115 -115
  328. package/package.json +78 -64
  329. package/scripts/fix-qwen-installation.js +144 -144
  330. package/agents/ez-integration-checker.md +0 -443
  331. package/agents/ez-nyquist-auditor.md +0 -176
  332. package/agents/ez-plan-checker.md +0 -706
  333. package/agents/ez-research-synthesizer.md +0 -247
  334. package/agents/ez-ui-auditor.md +0 -439
  335. package/agents/ez-ui-checker.md +0 -300
  336. package/agents/ez-ui-researcher.md +0 -353
  337. package/commands/ez/add-phase.md +0 -43
  338. package/commands/ez/add-todo.md +0 -47
  339. package/commands/ez/auth.md +0 -87
  340. package/commands/ez/autonomous.md +0 -41
  341. package/commands/ez/check-todos.md +0 -45
  342. package/commands/ez/cleanup.md +0 -18
  343. package/commands/ez/debug.md +0 -168
  344. package/commands/ez/health.md +0 -22
  345. package/commands/ez/insert-phase.md +0 -32
  346. package/commands/ez/join-discord.md +0 -18
  347. package/commands/ez/list-phase-assumptions.md +0 -46
  348. package/commands/ez/pause-work.md +0 -38
  349. package/commands/ez/plan-milestone-gaps.md +0 -34
  350. package/commands/ez/reapply-patches.md +0 -124
  351. package/commands/ez/remove-phase.md +0 -31
  352. package/commands/ez/research-phase.md +0 -190
  353. package/commands/ez/set-profile.md +0 -34
  354. package/commands/ez/stats.md +0 -18
  355. package/commands/ez/ui-phase.md +0 -34
  356. package/commands/ez/ui-review.md +0 -32
  357. package/commands/ez/validate-phase.md +0 -35
  358. package/ez-agents/templates/UI-SPEC.md +0 -100
  359. package/ez-agents/templates/VALIDATION.md +0 -76
  360. package/ez-agents/templates/context.md +0 -352
  361. package/ez-agents/templates/verification-report.md +0 -322
  362. package/ez-agents/workflows/research-phase.md +0 -74
  363. package/ez-agents/workflows/ui-phase.md +0 -290
  364. package/ez-agents/workflows/ui-review.md +0 -157
  365. package/ez-agents/workflows/validate-phase.md +0 -167
@@ -0,0 +1,829 @@
1
+ /**
2
+ * Gate 4: Security Baseline
3
+ *
4
+ * Validates security implementation including authentication, input validation,
5
+ * secrets management, and security anti-patterns.
6
+ *
7
+ * Checks:
8
+ * 1. Auth checker (session management, token handling, password hashing)
9
+ * 2. Input validation checker (sanitization, escaping, validation schemas)
10
+ * 3. Secrets scanner (hardcoded API keys, passwords, tokens)
11
+ * 4. Security anti-pattern detector (eval, execSync with user input, SQL concatenation)
12
+ *
13
+ * @module gates/gate-04-security
14
+ */
15
+
16
+ const { z } = require('zod');
17
+
18
+ /**
19
+ * Zod schema for a code file
20
+ * @type {z.ZodSchema}
21
+ */
22
+ const codeFileSchema = z.object({
23
+ /** File path */
24
+ path: z.string(),
25
+ /** File content */
26
+ content: z.string(),
27
+ /** File language (e.g., 'javascript', 'typescript') */
28
+ language: z.string().optional(),
29
+ });
30
+
31
+ /**
32
+ * Zod schema for environment variables configuration
33
+ * @type {z.ZodSchema}
34
+ */
35
+ const envConfigSchema = z.object({
36
+ /** Environment variable name */
37
+ name: z.string(),
38
+ /** Whether it's used in code */
39
+ isUsed: z.boolean().optional(),
40
+ /** Whether it has a default value */
41
+ hasDefault: z.boolean().optional(),
42
+ /** Whether it's marked as sensitive */
43
+ isSensitive: z.boolean().optional(),
44
+ });
45
+
46
+ /**
47
+ * Zod schema for authentication configuration
48
+ * @type {z.ZodSchema}
49
+ */
50
+ const authConfigSchema = z.object({
51
+ /** Authentication method (session, jwt, oauth, etc.) */
52
+ method: z.string().optional(),
53
+ /** Session store type (memory, redis, database) */
54
+ sessionStore: z.string().optional(),
55
+ /** Token expiration time */
56
+ tokenExpiration: z.string().optional(),
57
+ /** Password hashing algorithm */
58
+ hashingAlgorithm: z.string().optional(),
59
+ /** Whether HTTPS is enforced */
60
+ httpsEnforced: z.boolean().optional(),
61
+ /** Whether CSRF protection is enabled */
62
+ csrfProtection: z.boolean().optional(),
63
+ /** Whether rate limiting is enabled */
64
+ rateLimiting: z.boolean().optional(),
65
+ });
66
+
67
+ /**
68
+ * Zod schema for the gate context
69
+ * @type {z.ZodSchema}
70
+ */
71
+ const gateContextSchema = z.object({
72
+ /** Array of code files to analyze */
73
+ files: z.array(codeFileSchema).optional(),
74
+ /** Environment variable configuration */
75
+ envConfig: z.array(envConfigSchema).optional(),
76
+ /** Authentication configuration */
77
+ authConfig: authConfigSchema.optional(),
78
+ /** Input validation libraries used */
79
+ validationLibraries: z.array(z.string()).optional(),
80
+ /** Whether input validation is implemented */
81
+ hasInputValidation: z.boolean().optional(),
82
+ /** Known safe patterns (to reduce false positives) */
83
+ safePatterns: z.array(z.string()).optional(),
84
+ });
85
+
86
+ /**
87
+ * Security anti-patterns to detect
88
+ */
89
+ const SECURITY_ANTI_PATTERNS = {
90
+ /** eval() usage - allows arbitrary code execution */
91
+ eval: {
92
+ pattern: /\beval\s*\(/g,
93
+ severity: 'error',
94
+ message: 'eval() allows arbitrary code execution. Use safer alternatives like JSON.parse() or function maps.',
95
+ },
96
+ /** Function constructor - similar risks to eval */
97
+ functionConstructor: {
98
+ pattern: /\bnew\s+Function\s*\(/g,
99
+ severity: 'error',
100
+ message: 'Function constructor allows arbitrary code execution. Use safer alternatives.',
101
+ },
102
+ /** execSync with potential user input */
103
+ execSync: {
104
+ pattern: /\bexecSync\s*\([^)]*\)/g,
105
+ severity: 'error',
106
+ message: 'execSync with user input can lead to command injection. Use parameterized commands or avoid shell execution.',
107
+ },
108
+ /** exec with potential user input */
109
+ exec: {
110
+ pattern: /\bexec\s*\([^)]*\)/g,
111
+ severity: 'warning',
112
+ message: 'exec with user input can lead to command injection. Use execFile or spawn with argument arrays.',
113
+ },
114
+ /** spawn with shell option */
115
+ spawnShell: {
116
+ pattern: /\bspawn\s*\([^)]*shell\s*:\s*true/g,
117
+ severity: 'warning',
118
+ message: 'Using spawn with shell:true can lead to command injection. Avoid shell execution when possible.',
119
+ },
120
+ /** child_process exec variants */
121
+ childProcessExec: {
122
+ pattern: /child_process\s*\.\s*(exec|execSync|execFile|execFileSync)\s*\(/g,
123
+ severity: 'info',
124
+ message: 'Verify that child_process calls do not use unsanitized user input.',
125
+ },
126
+ };
127
+
128
+ /**
129
+ * Patterns for detecting hardcoded secrets
130
+ */
131
+ const SECRET_PATTERNS = {
132
+ /** AWS Access Key ID */
133
+ awsAccessKey: {
134
+ pattern: /AKIA[0-9A-Z]{16}/g,
135
+ message: 'Potential AWS Access Key ID detected. Use environment variables or secrets manager.',
136
+ severity: 'error',
137
+ },
138
+ /** AWS Secret Access Key (40 char base64) */
139
+ awsSecretKey: {
140
+ pattern: /['"]?(?:aws[_-]?secret|AWS[_-]?SECRET)[_]?[A-Z]*['"]?\s*[:=]\s*['"][A-Za-z0-9/+=]{40}['"]/gi,
141
+ message: 'Potential AWS Secret Access Key detected. Use environment variables or secrets manager.',
142
+ severity: 'error',
143
+ },
144
+ /** Generic API key patterns */
145
+ apiKey: {
146
+ pattern: /['"]?(?:api[_-]?key|apikey|API[_-]?KEY)[_]?[A-Z]*['"]?\s*[:=]\s*['"][a-zA-Z0-9_\-]{16,}['"]/gi,
147
+ message: 'Hardcoded API key detected. Use environment variables (e.g., process.env.API_KEY).',
148
+ severity: 'error',
149
+ },
150
+ /** Generic secret/token patterns */
151
+ secret: {
152
+ pattern: /['"]?(?:secret|token|auth[_-]?token|access[_-]?token|jwt|private[_-]?key)[_]?[A-Z]*['"]?\s*[:=]\s*['"][a-zA-Z0-9_\-]{8,}['"]/gi,
153
+ message: 'Hardcoded secret/token detected. Use environment variables or secrets manager.',
154
+ severity: 'error',
155
+ },
156
+ /** Password patterns */
157
+ password: {
158
+ pattern: /['"]?(?:password|passwd|pwd|PASSWORD|PASSWD)[_]?[A-Z]*['"]?\s*[:=]\s*['"][^'"]{4,}['"]/g,
159
+ message: 'Hardcoded password detected. Use environment variables or secrets manager.',
160
+ severity: 'error',
161
+ },
162
+ /** Database connection strings with credentials */
163
+ dbConnectionString: {
164
+ pattern: /(?:mongodb|postgres|mysql|redis):\/\/[^:]+:[^@]+@/gi,
165
+ message: 'Database connection string with embedded credentials. Use environment variables.',
166
+ severity: 'error',
167
+ },
168
+ /** Private key headers */
169
+ privateKey: {
170
+ pattern: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/g,
171
+ message: 'Private key embedded in code. Store in secure secrets manager or use environment variables.',
172
+ severity: 'error',
173
+ },
174
+ /** GitHub/GitLab tokens */
175
+ githubToken: {
176
+ pattern: /gh[pousr]_[A-Za-z0-9_]{36,}/g,
177
+ message: 'GitHub token detected. Use environment variables or secrets manager.',
178
+ severity: 'error',
179
+ },
180
+ /** Slack tokens */
181
+ slackToken: {
182
+ pattern: /xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,
183
+ message: 'Slack token detected. Use environment variables or secrets manager.',
184
+ severity: 'error',
185
+ },
186
+ /** Google API key */
187
+ googleApiKey: {
188
+ pattern: /AIza[0-9A-Za-z_-]{35}/g,
189
+ message: 'Google API key detected. Use environment variables or Google Secret Manager.',
190
+ severity: 'error',
191
+ },
192
+ /** Stripe keys */
193
+ stripeKey: {
194
+ pattern: /sk_live_[0-9a-zA-Z]{24,}/g,
195
+ message: 'Stripe live key detected. Use environment variables or secrets manager.',
196
+ severity: 'error',
197
+ },
198
+ /** Bearer token in headers */
199
+ bearerToken: {
200
+ pattern: /['"]Bearer\s+[a-zA-Z0-9_\-\.]+['"]/g,
201
+ message: 'Hardcoded Bearer token. Use dynamic token generation and environment variables for secrets.',
202
+ severity: 'warning',
203
+ },
204
+ };
205
+
206
+ /**
207
+ * SQL injection patterns
208
+ */
209
+ const SQL_INJECTION_PATTERNS = {
210
+ /** String concatenation in SQL queries */
211
+ stringConcat: {
212
+ pattern: /(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE)\s+[^;]*['"`]\s*\+\s*\w+/gi,
213
+ message: 'SQL query with string concatenation detected. Use parameterized queries or query builders.',
214
+ severity: 'error',
215
+ },
216
+ /** Template literal SQL */
217
+ templateLiteral: {
218
+ pattern: /`(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE)[^`]*\$\{[^}]+\}/gi,
219
+ message: 'SQL query with template literal interpolation. Use parameterized queries.',
220
+ severity: 'error',
221
+ },
222
+ /** query() with concatenated string */
223
+ queryConcat: {
224
+ pattern: /\.query\s*\(\s*[^)]*\+[^)]*\)/g,
225
+ message: 'Database query with string concatenation. Use parameterized queries.',
226
+ severity: 'error',
227
+ },
228
+ /** execute() with concatenated string */
229
+ executeConcat: {
230
+ pattern: /\.execute\s*\(\s*[^)]*\+[^)]*\)/g,
231
+ message: 'Database execute with string concatenation. Use parameterized queries.',
232
+ severity: 'error',
233
+ },
234
+ };
235
+
236
+ /**
237
+ * Input validation patterns to check for
238
+ */
239
+ const INPUT_VALIDATION_CHECKS = {
240
+ /** Express validator usage */
241
+ expressValidator: {
242
+ pattern: /express-validator|expressValidator|validationChain|body\(\)|query\(\)|param\(\)/g,
243
+ library: 'express-validator',
244
+ },
245
+ /** Joi validation */
246
+ joi: {
247
+ pattern: /joi\.|Joi\.|\.validate\(|\.schema\.validate/g,
248
+ library: 'joi',
249
+ },
250
+ /** Yup validation */
251
+ yup: {
252
+ pattern: /yup\.|Yup\.|\.validateSync\(|\.validate\(/g,
253
+ library: 'yup',
254
+ },
255
+ /** Zod validation */
256
+ zod: {
257
+ pattern: /zod\.|z\.|\.parse\(|\.safeParse\(|z\.string\(\)|z\.number\(\)/g,
258
+ library: 'zod',
259
+ },
260
+ /** class-validator */
261
+ classValidator: {
262
+ pattern: /class-validator|@IsString|@IsNumber|@IsEmail|@ValidateNested|validateOrReject/g,
263
+ library: 'class-validator',
264
+ },
265
+ /** AJV validation */
266
+ ajv: {
267
+ pattern: /ajv\.|Ajv\(|\.validate\(|\.compile\(/g,
268
+ library: 'ajv',
269
+ },
270
+ /** express-validator sanitize */
271
+ sanitization: {
272
+ pattern: /sanitize\(|\.escape\(|\.trim\(\)|\.normalizeEmail\(\)/g,
273
+ library: 'sanitization',
274
+ },
275
+ };
276
+
277
+ /**
278
+ * Secure session management patterns
279
+ */
280
+ const SECURE_SESSION_PATTERNS = {
281
+ /** Express session with secure config */
282
+ expressSession: {
283
+ pattern: /session\s*\(\s*\{[^}]*(?:secure|httpOnly|sameSite)[^}]*\}/g,
284
+ secure: true,
285
+ },
286
+ /** Redis session store */
287
+ redisStore: {
288
+ pattern: /connect-redis|RedisStore|redis\.createClient/g,
289
+ secure: true,
290
+ },
291
+ /** JWT with proper config */
292
+ jwtSecure: {
293
+ pattern: /jwt\.sign\s*\([^)]*expiresIn|jwt\.verify|jsonwebtoken/g,
294
+ secure: true,
295
+ },
296
+ /** Insecure session config patterns */
297
+ insecureSession: {
298
+ pattern: /cookie\s*:\s*\{[^}]*(?:secure\s*:\s*false|httpOnly\s*:\s*false)/g,
299
+ secure: false,
300
+ },
301
+ };
302
+
303
+ /**
304
+ * Check for eval() and similar dangerous patterns
305
+ * @param {string} code - Code content to analyze
306
+ * @returns {Array<{ path: string, message: string, severity: string }>}
307
+ */
308
+ function detectEvalUsage(code) {
309
+ const issues = [];
310
+
311
+ if (!code || typeof code !== 'string') {
312
+ return issues;
313
+ }
314
+
315
+ // Check for eval()
316
+ const evalMatches = code.match(SECURITY_ANTI_PATTERNS.eval.pattern);
317
+ if (evalMatches) {
318
+ for (const match of evalMatches) {
319
+ issues.push({
320
+ type: 'eval',
321
+ message: SECURITY_ANTI_PATTERNS.eval.message,
322
+ severity: SECURITY_ANTI_PATTERNS.eval.severity,
323
+ });
324
+ }
325
+ }
326
+
327
+ // Check for Function constructor
328
+ const funcMatches = code.match(SECURITY_ANTI_PATTERNS.functionConstructor.pattern);
329
+ if (funcMatches) {
330
+ for (const match of funcMatches) {
331
+ issues.push({
332
+ type: 'function-constructor',
333
+ message: SECURITY_ANTI_PATTERNS.functionConstructor.message,
334
+ severity: SECURITY_ANTI_PATTERNS.functionConstructor.severity,
335
+ });
336
+ }
337
+ }
338
+
339
+ return issues;
340
+ }
341
+
342
+ /**
343
+ * Check for execSync/exec with potential user input
344
+ * @param {string} code - Code content to analyze
345
+ * @returns {Array<{ type: string, message: string, severity: string }>}
346
+ */
347
+ function detectExecUsage(code) {
348
+ const issues = [];
349
+
350
+ if (!code || typeof code !== 'string') {
351
+ return issues;
352
+ }
353
+
354
+ // Check for execSync
355
+ const execSyncMatches = code.match(SECURITY_ANTI_PATTERNS.execSync.pattern);
356
+ if (execSyncMatches) {
357
+ for (const match of execSyncMatches) {
358
+ // Check if it contains user input indicators
359
+ const userInputIndicators = ['req.', 'request.', 'params', 'query', 'body', 'input', 'userInput'];
360
+ const hasUserInput = userInputIndicators.some(indicator => match.toLowerCase().includes(indicator.toLowerCase()));
361
+
362
+ if (hasUserInput || match.includes('+') || match.includes('${')) {
363
+ issues.push({
364
+ type: 'execSync-user-input',
365
+ message: SECURITY_ANTI_PATTERNS.execSync.message,
366
+ severity: SECURITY_ANTI_PATTERNS.execSync.severity,
367
+ });
368
+ } else {
369
+ // Still warn about execSync even without obvious user input
370
+ issues.push({
371
+ type: 'execSync',
372
+ message: 'execSync detected. Ensure no user input is passed to shell commands.',
373
+ severity: 'warning',
374
+ });
375
+ }
376
+ }
377
+ }
378
+
379
+ // Check for exec
380
+ const execMatches = code.match(SECURITY_ANTI_PATTERNS.exec.pattern);
381
+ if (execMatches) {
382
+ const userInputIndicators = ['req.', 'request.', 'params', 'query', 'body', 'input', 'userInput'];
383
+ for (const match of execMatches) {
384
+ const hasUserInput = userInputIndicators.some(indicator => match.toLowerCase().includes(indicator.toLowerCase()));
385
+
386
+ if (hasUserInput || match.includes('+') || match.includes('${')) {
387
+ issues.push({
388
+ type: 'exec-user-input',
389
+ message: SECURITY_ANTI_PATTERNS.exec.message,
390
+ severity: 'error',
391
+ });
392
+ }
393
+ }
394
+ }
395
+
396
+ return issues;
397
+ }
398
+
399
+ /**
400
+ * Check for SQL injection vulnerabilities
401
+ * @param {string} code - Code content to analyze
402
+ * @returns {Array<{ type: string, message: string, severity: string }>}
403
+ */
404
+ function detectSqlInjection(code) {
405
+ const issues = [];
406
+
407
+ if (!code || typeof code !== 'string') {
408
+ return issues;
409
+ }
410
+
411
+ // Check for string concatenation in SQL
412
+ for (const [name, config] of Object.entries(SQL_INJECTION_PATTERNS)) {
413
+ const matches = code.match(config.pattern);
414
+ if (matches) {
415
+ for (const match of matches) {
416
+ issues.push({
417
+ type: `sql-${name}`,
418
+ message: config.message,
419
+ severity: config.severity,
420
+ });
421
+ }
422
+ }
423
+ }
424
+
425
+ return issues;
426
+ }
427
+
428
+ /**
429
+ * Detect hardcoded secrets in code
430
+ * @param {string} code - Code content to analyze
431
+ * @returns {Array<{ type: string, message: string, severity: string }>}
432
+ */
433
+ function detectHardcodedSecrets(code) {
434
+ const issues = [];
435
+
436
+ if (!code || typeof code !== 'string') {
437
+ return issues;
438
+ }
439
+
440
+ // Check for each secret pattern
441
+ for (const [name, config] of Object.entries(SECRET_PATTERNS)) {
442
+ const matches = code.match(config.pattern);
443
+ if (matches && matches.length > 0) {
444
+ for (const match of matches) {
445
+ // Skip if it's clearly using environment variables
446
+ if (match.includes('process.env') || match.includes('process.env')) {
447
+ continue;
448
+ }
449
+
450
+ // Skip example/placeholder values
451
+ if (match.includes('YOUR_') || match.includes('xxx') || match.includes('example')) {
452
+ continue;
453
+ }
454
+
455
+ issues.push({
456
+ type: `secret-${name}`,
457
+ message: config.message,
458
+ severity: config.severity,
459
+ });
460
+ }
461
+ }
462
+ }
463
+
464
+ return issues;
465
+ }
466
+
467
+ /**
468
+ * Check for secure session management
469
+ * @param {string} code - Code content to analyze
470
+ * @param {Object} authConfig - Authentication configuration
471
+ * @returns {{ secure: boolean, issues: Array<{ type: string, message: string }> }}
472
+ */
473
+ function checkSessionSecurity(code, authConfig = {}) {
474
+ const issues = [];
475
+ let isSecure = true;
476
+
477
+ if (!code || typeof code !== 'string') {
478
+ return { secure: true, issues }; // No session code to check
479
+ }
480
+
481
+ // Check for insecure session configurations
482
+ const insecureMatches = code.match(SECURE_SESSION_PATTERNS.insecureSession.pattern);
483
+ if (insecureMatches) {
484
+ isSecure = false;
485
+ issues.push({
486
+ type: 'insecure-session',
487
+ message: 'Insecure session configuration detected. Ensure secure: true, httpOnly: true, sameSite: strict.',
488
+ });
489
+ }
490
+
491
+ // Check for secure patterns
492
+ const hasSecureSession = Object.values(SECURE_SESSION_PATTERNS).some(pattern =>
493
+ pattern.secure && code.match(pattern.pattern)
494
+ );
495
+
496
+ // Check auth config
497
+ if (authConfig) {
498
+ if (authConfig.sessionStore === 'memory') {
499
+ issues.push({
500
+ type: 'memory-session-store',
501
+ message: 'In-memory session store is not suitable for production. Use Redis or database.',
502
+ });
503
+ isSecure = false;
504
+ }
505
+
506
+ if (authConfig.httpsEnforced === false) {
507
+ issues.push({
508
+ type: 'no-https',
509
+ message: 'HTTPS is not enforced. Always use HTTPS in production.',
510
+ });
511
+ isSecure = false;
512
+ }
513
+
514
+ if (authConfig.csrfProtection === false) {
515
+ issues.push({
516
+ type: 'no-csrf',
517
+ message: 'CSRF protection is disabled. Enable CSRF protection for state-changing operations.',
518
+ });
519
+ isSecure = false;
520
+ }
521
+
522
+ if (authConfig.hashingAlgorithm && ['md5', 'sha1', 'sha256'].includes(authConfig.hashingAlgorithm.toLowerCase())) {
523
+ issues.push({
524
+ type: 'weak-hashing',
525
+ message: `Weak password hashing algorithm (${authConfig.hashingAlgorithm}). Use bcrypt, scrypt, or argon2.`,
526
+ });
527
+ isSecure = false;
528
+ }
529
+ }
530
+
531
+ return { secure: isSecure, issues };
532
+ }
533
+
534
+ /**
535
+ * Check for input validation implementation
536
+ * @param {string} code - Code content to analyze
537
+ * @param {Array} validationLibraries - List of validation libraries used
538
+ * @returns {{ hasValidation: boolean, libraries: string[], issues: Array<{ type: string, message: string }> }}
539
+ */
540
+ function checkInputValidation(code, validationLibraries = []) {
541
+ const issues = [];
542
+ const foundLibraries = [];
543
+ let hasValidation = false;
544
+
545
+ if (!code || typeof code !== 'string') {
546
+ return { hasValidation: false, libraries: [], issues };
547
+ }
548
+
549
+ // Check for validation library usage
550
+ for (const [name, config] of Object.entries(INPUT_VALIDATION_CHECKS)) {
551
+ if (code.match(config.pattern)) {
552
+ foundLibraries.push(config.library || name);
553
+ hasValidation = true;
554
+ }
555
+ }
556
+
557
+ // Check for manual validation patterns
558
+ const manualValidationPatterns = [
559
+ /typeof\s+\w+\s*===?\s*['"]string['"]/,
560
+ /Array\.isArray\s*\(/,
561
+ /Number\.isInteger\s*\(/,
562
+ /parseInt\s*\(/,
563
+ /parseFloat\s*\(/,
564
+ /\.test\s*\(/,
565
+ /\.match\s*\(/,
566
+ ];
567
+
568
+ let manualValidationCount = 0;
569
+ for (const pattern of manualValidationPatterns) {
570
+ if (code.match(pattern)) {
571
+ manualValidationCount++;
572
+ }
573
+ }
574
+
575
+ if (manualValidationCount > 0 && !hasValidation) {
576
+ // Manual validation detected - this is a warning, not an error
577
+ issues.push({
578
+ type: 'manual-validation',
579
+ message: 'Manual input validation detected. Consider using a validation library for consistency.',
580
+ });
581
+ hasValidation = true;
582
+ }
583
+
584
+ // Check for missing validation on user input
585
+ const userInputPatterns = [
586
+ /req\.body/,
587
+ /req\.query/,
588
+ /req\.params/,
589
+ /request\.body/,
590
+ /request\.query/,
591
+ /request\.params/,
592
+ ];
593
+
594
+ const hasUserInput = userInputPatterns.some(pattern => code.match(pattern));
595
+
596
+ if (hasUserInput && !hasValidation) {
597
+ issues.push({
598
+ type: 'missing-validation',
599
+ message: 'User input detected without validation. Add input validation using a library or manual checks.',
600
+ });
601
+ }
602
+
603
+ return {
604
+ hasValidation,
605
+ libraries: [...new Set(foundLibraries)],
606
+ issues,
607
+ };
608
+ }
609
+
610
+ /**
611
+ * Check for environment variable usage for secrets
612
+ * @param {string} code - Code content to analyze
613
+ * @param {Array} envConfig - Environment configuration
614
+ * @returns {{ usesEnvVars: boolean, issues: Array<{ type: string, message: string }> }}
615
+ */
616
+ function checkEnvVarUsage(code, envConfig = []) {
617
+ const issues = [];
618
+ let usesEnvVars = false;
619
+
620
+ if (!code || typeof code !== 'string') {
621
+ return { usesEnvVars: false, issues };
622
+ }
623
+
624
+ // Check for process.env usage
625
+ const envVarUsage = code.match(/process\.env\.[A-Z_]+/g);
626
+ if (envVarUsage && envVarUsage.length > 0) {
627
+ usesEnvVars = true;
628
+ }
629
+
630
+ // Check for sensitive values that should use env vars
631
+ const sensitivePatterns = [
632
+ { pattern: /password\s*[:=]\s*['"][^'"]+['"]/gi, name: 'password' },
633
+ { pattern: /secret\s*[:=]\s*['"][^'"]+['"]/gi, name: 'secret' },
634
+ { pattern: /apiKey\s*[:=]\s*['"][^'"]+['"]/gi, name: 'API key' },
635
+ { pattern: /token\s*[:=]\s*['"][^'"]+['"]/gi, name: 'token' },
636
+ { pattern: /privateKey\s*[:=]\s*['"][^'"]+['"]/gi, name: 'private key' },
637
+ ];
638
+
639
+ for (const { pattern, name } of sensitivePatterns) {
640
+ const matches = code.match(pattern);
641
+ if (matches) {
642
+ for (const match of matches) {
643
+ if (!match.includes('process.env')) {
644
+ issues.push({
645
+ type: 'hardcoded-sensitive',
646
+ message: `Hardcoded ${name} detected. Use environment variable (e.g., process.env.${name.toUpperCase()}).`,
647
+ });
648
+ }
649
+ }
650
+ }
651
+ }
652
+
653
+ return { usesEnvVars, issues };
654
+ }
655
+
656
+ /**
657
+ * Analyze code file for security issues
658
+ * @param {Object} file - Code file object
659
+ * @param {Object} authConfig - Authentication configuration
660
+ * @returns {{ errors: Array, warnings: Array }}
661
+ */
662
+ function analyzeSecurityFile(file, authConfig = {}) {
663
+ const errors = [];
664
+ const warnings = [];
665
+
666
+ if (!file || !file.content) {
667
+ return { errors, warnings };
668
+ }
669
+
670
+ const filePath = file.path || 'unknown';
671
+ const code = file.content;
672
+
673
+ // Check for eval() usage
674
+ const evalIssues = detectEvalUsage(code);
675
+ for (const issue of evalIssues) {
676
+ (issue.severity === 'error' ? errors : warnings).push({
677
+ path: filePath,
678
+ message: issue.message,
679
+ });
680
+ }
681
+
682
+ // Check for exec usage
683
+ const execIssues = detectExecUsage(code);
684
+ for (const issue of execIssues) {
685
+ (issue.severity === 'error' ? errors : warnings).push({
686
+ path: filePath,
687
+ message: issue.message,
688
+ });
689
+ }
690
+
691
+ // Check for SQL injection
692
+ const sqlIssues = detectSqlInjection(code);
693
+ for (const issue of sqlIssues) {
694
+ (issue.severity === 'error' ? errors : warnings).push({
695
+ path: filePath,
696
+ message: issue.message,
697
+ });
698
+ }
699
+
700
+ // Check for hardcoded secrets
701
+ const secretIssues = detectHardcodedSecrets(code);
702
+ for (const issue of secretIssues) {
703
+ (issue.severity === 'error' ? errors : warnings).push({
704
+ path: filePath,
705
+ message: issue.message,
706
+ });
707
+ }
708
+
709
+ // Check session security
710
+ const sessionResult = checkSessionSecurity(code, authConfig);
711
+ for (const issue of sessionResult.issues) {
712
+ errors.push({
713
+ path: filePath,
714
+ message: issue.message,
715
+ });
716
+ }
717
+
718
+ // Check input validation
719
+ const validationResult = checkInputValidation(code);
720
+ for (const issue of validationResult.issues) {
721
+ warnings.push({
722
+ path: filePath,
723
+ message: issue.message,
724
+ });
725
+ }
726
+
727
+ // Check environment variable usage
728
+ const envResult = checkEnvVarUsage(code);
729
+ for (const issue of envResult.issues) {
730
+ errors.push({
731
+ path: filePath,
732
+ message: issue.message,
733
+ });
734
+ }
735
+
736
+ return { errors, warnings };
737
+ }
738
+
739
+ /**
740
+ * Gate 4 Executor: Security Baseline Check
741
+ *
742
+ * @param {Object} context - Gate context (validated against gateContextSchema)
743
+ * @returns {Promise<{ passed: boolean, errors: Array<{path: string, message: string}>, warnings: string[] }>}
744
+ */
745
+ async function executeGate4(context) {
746
+ const errors = [];
747
+ const warnings = [];
748
+
749
+ // Extract auth config
750
+ const authConfig = context.authConfig || {};
751
+
752
+ // Analyze each file
753
+ if (context.files && Array.isArray(context.files)) {
754
+ for (const file of context.files) {
755
+ const result = analyzeSecurityFile(file, authConfig);
756
+ errors.push(...result.errors);
757
+ warnings.push(...result.warnings.map(w =>
758
+ typeof w === 'string' ? w : `${w.path}: ${w.message}`
759
+ ));
760
+ }
761
+ }
762
+
763
+ // Check for missing input validation at project level
764
+ if (context.hasInputValidation === false) {
765
+ errors.push({
766
+ path: 'input-validation',
767
+ message: 'No input validation detected. Implement input validation using a library (express-validator, joi, zod, etc.).',
768
+ });
769
+ }
770
+
771
+ // Check auth configuration
772
+ if (authConfig) {
773
+ // Check for weak hashing
774
+ if (authConfig.hashingAlgorithm && ['md5', 'sha1', 'sha256'].includes(authConfig.hashingAlgorithm.toLowerCase())) {
775
+ errors.push({
776
+ path: 'authConfig.hashingAlgorithm',
777
+ message: `Weak password hashing (${authConfig.hashingAlgorithm}). Use bcrypt, scrypt, or argon2.`,
778
+ });
779
+ }
780
+
781
+ // Check for missing HTTPS
782
+ if (authConfig.httpsEnforced === false) {
783
+ warnings.push('HTTPS is not enforced. Consider enforcing HTTPS in production.');
784
+ }
785
+
786
+ // Check for missing CSRF protection
787
+ if (authConfig.csrfProtection === false) {
788
+ warnings.push('CSRF protection is disabled. Consider enabling for state-changing operations.');
789
+ }
790
+ }
791
+
792
+ return {
793
+ passed: errors.length === 0,
794
+ errors,
795
+ warnings,
796
+ };
797
+ }
798
+
799
+ /**
800
+ * Create and register Gate 4 with a QualityGate instance
801
+ *
802
+ * @param {QualityGate} gateCoordinator - QualityGate coordinator instance
803
+ * @returns {void}
804
+ */
805
+ function registerGate4(gateCoordinator) {
806
+ gateCoordinator.registerGate('gate-04-security', gateContextSchema, executeGate4);
807
+ }
808
+
809
+ module.exports = {
810
+ executeGate4,
811
+ registerGate4,
812
+ codeFileSchema,
813
+ envConfigSchema,
814
+ authConfigSchema,
815
+ gateContextSchema,
816
+ SECURITY_ANTI_PATTERNS,
817
+ SECRET_PATTERNS,
818
+ SQL_INJECTION_PATTERNS,
819
+ INPUT_VALIDATION_CHECKS,
820
+ SECURE_SESSION_PATTERNS,
821
+ detectEvalUsage,
822
+ detectExecUsage,
823
+ detectSqlInjection,
824
+ detectHardcodedSecrets,
825
+ checkSessionSecurity,
826
+ checkInputValidation,
827
+ checkEnvVarUsage,
828
+ analyzeSecurityFile,
829
+ };