@avi770/testteam 2.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1201) hide show
  1. package/CHANGELOG.md +188 -3
  2. package/README.md +111 -20
  3. package/bin/testteam.js +32 -4
  4. package/dist/agents/01-analyst.d.ts +2 -2
  5. package/dist/agents/01-analyst.js +1 -1
  6. package/dist/agents/02-seed-architect.d.ts +2 -2
  7. package/dist/agents/02-seed-architect.js +2 -2
  8. package/dist/agents/03-test-generator.d.ts +2 -2
  9. package/dist/agents/03-test-generator.js +2 -2
  10. package/dist/agents/04-unit-runner.d.ts +2 -2
  11. package/dist/agents/04-unit-runner.d.ts.map +1 -1
  12. package/dist/agents/04-unit-runner.js +12 -3
  13. package/dist/agents/04-unit-runner.js.map +1 -1
  14. package/dist/agents/05-browser-crawler.d.ts +2 -2
  15. package/dist/agents/05-browser-crawler.d.ts.map +1 -1
  16. package/dist/agents/05-browser-crawler.js +24 -12
  17. package/dist/agents/05-browser-crawler.js.map +1 -1
  18. package/dist/agents/06-api-exerciser.d.ts +2 -2
  19. package/dist/agents/06-api-exerciser.js +2 -2
  20. package/dist/agents/07-security-scout.d.ts +2 -2
  21. package/dist/agents/07-security-scout.js +2 -2
  22. package/dist/agents/08-a11y-guardian.d.ts +2 -2
  23. package/dist/agents/08-a11y-guardian.d.ts.map +1 -1
  24. package/dist/agents/08-a11y-guardian.js +9 -5
  25. package/dist/agents/08-a11y-guardian.js.map +1 -1
  26. package/dist/agents/09-healer.d.ts +2 -2
  27. package/dist/agents/09-healer.js +2 -2
  28. package/dist/agents/10-reporter.d.ts +2 -2
  29. package/dist/agents/10-reporter.d.ts.map +1 -1
  30. package/dist/agents/10-reporter.js +55 -27
  31. package/dist/agents/10-reporter.js.map +1 -1
  32. package/dist/agents/100-error-handling-auditor.d.ts +63 -0
  33. package/dist/agents/100-error-handling-auditor.d.ts.map +1 -0
  34. package/dist/agents/100-error-handling-auditor.js +334 -0
  35. package/dist/agents/100-error-handling-auditor.js.map +1 -0
  36. package/dist/agents/101-rate-limit-auditor.d.ts +72 -0
  37. package/dist/agents/101-rate-limit-auditor.d.ts.map +1 -0
  38. package/dist/agents/101-rate-limit-auditor.js +295 -0
  39. package/dist/agents/101-rate-limit-auditor.js.map +1 -0
  40. package/dist/agents/102-dockerfile-auditor.d.ts +62 -0
  41. package/dist/agents/102-dockerfile-auditor.d.ts.map +1 -0
  42. package/dist/agents/102-dockerfile-auditor.js +337 -0
  43. package/dist/agents/102-dockerfile-auditor.js.map +1 -0
  44. package/dist/agents/103-ci-workflow-auditor.d.ts +57 -0
  45. package/dist/agents/103-ci-workflow-auditor.d.ts.map +1 -0
  46. package/dist/agents/103-ci-workflow-auditor.js +247 -0
  47. package/dist/agents/103-ci-workflow-auditor.js.map +1 -0
  48. package/dist/agents/104-n-plus-one-detector.d.ts +57 -0
  49. package/dist/agents/104-n-plus-one-detector.d.ts.map +1 -0
  50. package/dist/agents/104-n-plus-one-detector.js +329 -0
  51. package/dist/agents/104-n-plus-one-detector.js.map +1 -0
  52. package/dist/agents/105-unbounded-query-auditor.d.ts +50 -0
  53. package/dist/agents/105-unbounded-query-auditor.d.ts.map +1 -0
  54. package/dist/agents/105-unbounded-query-auditor.js +284 -0
  55. package/dist/agents/105-unbounded-query-auditor.js.map +1 -0
  56. package/dist/agents/106-hardcoded-config-auditor.d.ts +54 -0
  57. package/dist/agents/106-hardcoded-config-auditor.d.ts.map +1 -0
  58. package/dist/agents/106-hardcoded-config-auditor.js +251 -0
  59. package/dist/agents/106-hardcoded-config-auditor.js.map +1 -0
  60. package/dist/agents/107-open-redirect-detector.d.ts +52 -0
  61. package/dist/agents/107-open-redirect-detector.d.ts.map +1 -0
  62. package/dist/agents/107-open-redirect-detector.js +263 -0
  63. package/dist/agents/107-open-redirect-detector.js.map +1 -0
  64. package/dist/agents/108-sql-injection-detector.d.ts +51 -0
  65. package/dist/agents/108-sql-injection-detector.d.ts.map +1 -0
  66. package/dist/agents/108-sql-injection-detector.js +323 -0
  67. package/dist/agents/108-sql-injection-detector.js.map +1 -0
  68. package/dist/agents/109-path-traversal-detector.d.ts +51 -0
  69. package/dist/agents/109-path-traversal-detector.d.ts.map +1 -0
  70. package/dist/agents/109-path-traversal-detector.js +244 -0
  71. package/dist/agents/109-path-traversal-detector.js.map +1 -0
  72. package/dist/agents/11-fixer.d.ts +4 -2
  73. package/dist/agents/11-fixer.d.ts.map +1 -1
  74. package/dist/agents/11-fixer.js +52 -11
  75. package/dist/agents/11-fixer.js.map +1 -1
  76. package/dist/agents/110-mass-assignment-detector.d.ts +52 -0
  77. package/dist/agents/110-mass-assignment-detector.d.ts.map +1 -0
  78. package/dist/agents/110-mass-assignment-detector.js +199 -0
  79. package/dist/agents/110-mass-assignment-detector.js.map +1 -0
  80. package/dist/agents/111-dynamic-eval-detector.d.ts +46 -0
  81. package/dist/agents/111-dynamic-eval-detector.d.ts.map +1 -0
  82. package/dist/agents/111-dynamic-eval-detector.js +233 -0
  83. package/dist/agents/111-dynamic-eval-detector.js.map +1 -0
  84. package/dist/agents/112-taint-tracker.d.ts +226 -0
  85. package/dist/agents/112-taint-tracker.d.ts.map +1 -0
  86. package/dist/agents/112-taint-tracker.js +1273 -0
  87. package/dist/agents/112-taint-tracker.js.map +1 -0
  88. package/dist/agents/113-response-contract-auditor.d.ts +92 -0
  89. package/dist/agents/113-response-contract-auditor.d.ts.map +1 -0
  90. package/dist/agents/113-response-contract-auditor.js +694 -0
  91. package/dist/agents/113-response-contract-auditor.js.map +1 -0
  92. package/dist/agents/114-static-a11y-auditor.d.ts +66 -0
  93. package/dist/agents/114-static-a11y-auditor.d.ts.map +1 -0
  94. package/dist/agents/114-static-a11y-auditor.js +377 -0
  95. package/dist/agents/114-static-a11y-auditor.js.map +1 -0
  96. package/dist/agents/115-multihop-taint-tracker.d.ts +84 -0
  97. package/dist/agents/115-multihop-taint-tracker.d.ts.map +1 -0
  98. package/dist/agents/115-multihop-taint-tracker.js +340 -0
  99. package/dist/agents/115-multihop-taint-tracker.js.map +1 -0
  100. package/dist/agents/116-runtime-contract-capture.d.ts +79 -0
  101. package/dist/agents/116-runtime-contract-capture.d.ts.map +1 -0
  102. package/dist/agents/116-runtime-contract-capture.js +274 -0
  103. package/dist/agents/116-runtime-contract-capture.js.map +1 -0
  104. package/dist/agents/117-aria-rule-engine.d.ts +52 -0
  105. package/dist/agents/117-aria-rule-engine.d.ts.map +1 -0
  106. package/dist/agents/117-aria-rule-engine.js +415 -0
  107. package/dist/agents/117-aria-rule-engine.js.map +1 -0
  108. package/dist/agents/118-insecure-crypto-auditor.d.ts +48 -0
  109. package/dist/agents/118-insecure-crypto-auditor.d.ts.map +1 -0
  110. package/dist/agents/118-insecure-crypto-auditor.js +232 -0
  111. package/dist/agents/118-insecure-crypto-auditor.js.map +1 -0
  112. package/dist/agents/119-secrets-scanner.d.ts +44 -0
  113. package/dist/agents/119-secrets-scanner.d.ts.map +1 -0
  114. package/dist/agents/119-secrets-scanner.js +242 -0
  115. package/dist/agents/119-secrets-scanner.js.map +1 -0
  116. package/dist/agents/12-ux-inspector.d.ts +2 -2
  117. package/dist/agents/12-ux-inspector.d.ts.map +1 -1
  118. package/dist/agents/12-ux-inspector.js +8 -4
  119. package/dist/agents/12-ux-inspector.js.map +1 -1
  120. package/dist/agents/120-async-safety-auditor.d.ts +48 -0
  121. package/dist/agents/120-async-safety-auditor.d.ts.map +1 -0
  122. package/dist/agents/120-async-safety-auditor.js +250 -0
  123. package/dist/agents/120-async-safety-auditor.js.map +1 -0
  124. package/dist/agents/13-performance-profiler.d.ts +2 -2
  125. package/dist/agents/13-performance-profiler.d.ts.map +1 -1
  126. package/dist/agents/13-performance-profiler.js +5 -4
  127. package/dist/agents/13-performance-profiler.js.map +1 -1
  128. package/dist/agents/14-data-integrity-auditor.d.ts +2 -2
  129. package/dist/agents/14-data-integrity-auditor.js +4 -4
  130. package/dist/agents/14-data-integrity-auditor.js.map +1 -1
  131. package/dist/agents/15-regression-sentinel.d.ts +6 -4
  132. package/dist/agents/15-regression-sentinel.d.ts.map +1 -1
  133. package/dist/agents/15-regression-sentinel.js +5 -4
  134. package/dist/agents/15-regression-sentinel.js.map +1 -1
  135. package/dist/agents/16-chaos-agent.d.ts +2 -2
  136. package/dist/agents/16-chaos-agent.d.ts.map +1 -1
  137. package/dist/agents/16-chaos-agent.js +11 -4
  138. package/dist/agents/16-chaos-agent.js.map +1 -1
  139. package/dist/agents/17-documentation-validator.d.ts +2 -2
  140. package/dist/agents/17-documentation-validator.d.ts.map +1 -1
  141. package/dist/agents/17-documentation-validator.js +5 -2
  142. package/dist/agents/17-documentation-validator.js.map +1 -1
  143. package/dist/agents/18-integration-watchdog.d.ts +2 -2
  144. package/dist/agents/18-integration-watchdog.d.ts.map +1 -1
  145. package/dist/agents/18-integration-watchdog.js +5 -2
  146. package/dist/agents/18-integration-watchdog.js.map +1 -1
  147. package/dist/agents/19-tenant-isolation-auditor.d.ts +2 -2
  148. package/dist/agents/19-tenant-isolation-auditor.js +4 -4
  149. package/dist/agents/19-tenant-isolation-auditor.js.map +1 -1
  150. package/dist/agents/20-workflow-completion-tester.d.ts +2 -2
  151. package/dist/agents/20-workflow-completion-tester.d.ts.map +1 -1
  152. package/dist/agents/20-workflow-completion-tester.js +10 -6
  153. package/dist/agents/20-workflow-completion-tester.js.map +1 -1
  154. package/dist/agents/21-state-session-tester.d.ts +2 -2
  155. package/dist/agents/21-state-session-tester.d.ts.map +1 -1
  156. package/dist/agents/21-state-session-tester.js +15 -5
  157. package/dist/agents/21-state-session-tester.js.map +1 -1
  158. package/dist/agents/22-email-notification-verifier.d.ts +2 -2
  159. package/dist/agents/22-email-notification-verifier.js +2 -2
  160. package/dist/agents/23-migration-tester.d.ts +2 -2
  161. package/dist/agents/23-migration-tester.js +1 -1
  162. package/dist/agents/24-signup-onboarding-tester.d.ts +2 -2
  163. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -1
  164. package/dist/agents/24-signup-onboarding-tester.js +13 -10
  165. package/dist/agents/24-signup-onboarding-tester.js.map +1 -1
  166. package/dist/agents/25-crud-flow-tester.d.ts +2 -2
  167. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -1
  168. package/dist/agents/25-crud-flow-tester.js +12 -6
  169. package/dist/agents/25-crud-flow-tester.js.map +1 -1
  170. package/dist/agents/26-form-validator.d.ts +2 -2
  171. package/dist/agents/26-form-validator.d.ts.map +1 -1
  172. package/dist/agents/26-form-validator.js +12 -6
  173. package/dist/agents/26-form-validator.js.map +1 -1
  174. package/dist/agents/27-search-filter-tester.d.ts +2 -2
  175. package/dist/agents/27-search-filter-tester.d.ts.map +1 -1
  176. package/dist/agents/27-search-filter-tester.js +12 -6
  177. package/dist/agents/27-search-filter-tester.js.map +1 -1
  178. package/dist/agents/28-navigation-routing-tester.d.ts +2 -2
  179. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -1
  180. package/dist/agents/28-navigation-routing-tester.js +12 -6
  181. package/dist/agents/28-navigation-routing-tester.js.map +1 -1
  182. package/dist/agents/29-responsive-interaction-tester.d.ts +2 -2
  183. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -1
  184. package/dist/agents/29-responsive-interaction-tester.js +12 -6
  185. package/dist/agents/29-responsive-interaction-tester.js.map +1 -1
  186. package/dist/agents/30-multi-user-scenario-tester.d.ts +2 -2
  187. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -1
  188. package/dist/agents/30-multi-user-scenario-tester.js +20 -13
  189. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -1
  190. package/dist/agents/31-load-tester.d.ts +2 -2
  191. package/dist/agents/31-load-tester.js +2 -2
  192. package/dist/agents/32-memory-leak-detector.d.ts +2 -2
  193. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -1
  194. package/dist/agents/32-memory-leak-detector.js +5 -4
  195. package/dist/agents/32-memory-leak-detector.js.map +1 -1
  196. package/dist/agents/33-bundle-analyzer.d.ts +2 -2
  197. package/dist/agents/33-bundle-analyzer.js +1 -1
  198. package/dist/agents/34-xss-scanner.d.ts +2 -2
  199. package/dist/agents/34-xss-scanner.d.ts.map +1 -1
  200. package/dist/agents/34-xss-scanner.js +12 -6
  201. package/dist/agents/34-xss-scanner.js.map +1 -1
  202. package/dist/agents/35-csrf-tester.d.ts +2 -2
  203. package/dist/agents/35-csrf-tester.js +2 -2
  204. package/dist/agents/36-auth-fuzzer.d.ts +2 -2
  205. package/dist/agents/36-auth-fuzzer.js +2 -2
  206. package/dist/agents/37-dependency-scanner.d.ts +2 -2
  207. package/dist/agents/37-dependency-scanner.js +1 -1
  208. package/dist/agents/38-secrets-scanner.d.ts +2 -2
  209. package/dist/agents/38-secrets-scanner.d.ts.map +1 -1
  210. package/dist/agents/38-secrets-scanner.js +39 -4
  211. package/dist/agents/38-secrets-scanner.js.map +1 -1
  212. package/dist/agents/39-api-contract-tester.d.ts +2 -2
  213. package/dist/agents/39-api-contract-tester.js +2 -2
  214. package/dist/agents/40-rate-limit-tester.d.ts +2 -2
  215. package/dist/agents/40-rate-limit-tester.js +2 -2
  216. package/dist/agents/41-api-pagination-tester.d.ts +2 -2
  217. package/dist/agents/41-api-pagination-tester.js +2 -2
  218. package/dist/agents/42-graphql-tester.d.ts +2 -2
  219. package/dist/agents/42-graphql-tester.js +2 -2
  220. package/dist/agents/43-data-consistency-checker.d.ts +2 -2
  221. package/dist/agents/43-data-consistency-checker.js +3 -3
  222. package/dist/agents/44-backup-recovery-tester.d.ts +2 -2
  223. package/dist/agents/44-backup-recovery-tester.js +1 -1
  224. package/dist/agents/45-data-privacy-scanner.d.ts +2 -2
  225. package/dist/agents/45-data-privacy-scanner.js +3 -3
  226. package/dist/agents/46-seo-auditor.d.ts +2 -2
  227. package/dist/agents/46-seo-auditor.d.ts.map +1 -1
  228. package/dist/agents/46-seo-auditor.js +12 -6
  229. package/dist/agents/46-seo-auditor.js.map +1 -1
  230. package/dist/agents/47-social-preview-tester.d.ts +2 -2
  231. package/dist/agents/47-social-preview-tester.d.ts.map +1 -1
  232. package/dist/agents/47-social-preview-tester.js +12 -6
  233. package/dist/agents/47-social-preview-tester.js.map +1 -1
  234. package/dist/agents/48-lighthouse-auditor.d.ts +2 -2
  235. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -1
  236. package/dist/agents/48-lighthouse-auditor.js +5 -4
  237. package/dist/agents/48-lighthouse-auditor.js.map +1 -1
  238. package/dist/agents/49-i18n-tester.d.ts +2 -2
  239. package/dist/agents/49-i18n-tester.d.ts.map +1 -1
  240. package/dist/agents/49-i18n-tester.js +12 -6
  241. package/dist/agents/49-i18n-tester.js.map +1 -1
  242. package/dist/agents/50-timezone-tester.d.ts +2 -2
  243. package/dist/agents/50-timezone-tester.d.ts.map +1 -1
  244. package/dist/agents/50-timezone-tester.js +40 -33
  245. package/dist/agents/50-timezone-tester.js.map +1 -1
  246. package/dist/agents/51-error-recovery-tester.d.ts +2 -2
  247. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -1
  248. package/dist/agents/51-error-recovery-tester.js +12 -7
  249. package/dist/agents/51-error-recovery-tester.js.map +1 -1
  250. package/dist/agents/52-offline-mode-tester.d.ts +2 -2
  251. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -1
  252. package/dist/agents/52-offline-mode-tester.js +12 -7
  253. package/dist/agents/52-offline-mode-tester.js.map +1 -1
  254. package/dist/agents/53-graceful-degradation-tester.d.ts +2 -2
  255. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -1
  256. package/dist/agents/53-graceful-degradation-tester.js +10 -3
  257. package/dist/agents/53-graceful-degradation-tester.js.map +1 -1
  258. package/dist/agents/54-websocket-tester.d.ts +2 -2
  259. package/dist/agents/54-websocket-tester.d.ts.map +1 -1
  260. package/dist/agents/54-websocket-tester.js +12 -6
  261. package/dist/agents/54-websocket-tester.js.map +1 -1
  262. package/dist/agents/55-realtime-sync-tester.d.ts +2 -2
  263. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -1
  264. package/dist/agents/55-realtime-sync-tester.js +101 -96
  265. package/dist/agents/55-realtime-sync-tester.js.map +1 -1
  266. package/dist/agents/56-file-upload-tester.d.ts +2 -2
  267. package/dist/agents/56-file-upload-tester.d.ts.map +1 -1
  268. package/dist/agents/56-file-upload-tester.js +17 -13
  269. package/dist/agents/56-file-upload-tester.js.map +1 -1
  270. package/dist/agents/57-export-tester.d.ts +2 -2
  271. package/dist/agents/57-export-tester.d.ts.map +1 -1
  272. package/dist/agents/57-export-tester.js +8 -4
  273. package/dist/agents/57-export-tester.js.map +1 -1
  274. package/dist/agents/58-payment-flow-tester.d.ts +2 -2
  275. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -1
  276. package/dist/agents/58-payment-flow-tester.js +8 -4
  277. package/dist/agents/58-payment-flow-tester.js.map +1 -1
  278. package/dist/agents/59-ssl-tls-auditor.d.ts +2 -2
  279. package/dist/agents/59-ssl-tls-auditor.js +2 -2
  280. package/dist/agents/60-dns-cdn-tester.d.ts +2 -2
  281. package/dist/agents/60-dns-cdn-tester.js +2 -2
  282. package/dist/agents/61-docker-health-checker.d.ts +2 -2
  283. package/dist/agents/61-docker-health-checker.js +1 -1
  284. package/dist/agents/62-env-config-validator.d.ts +2 -2
  285. package/dist/agents/62-env-config-validator.js +1 -1
  286. package/dist/agents/63-log-quality-auditor.d.ts +2 -2
  287. package/dist/agents/63-log-quality-auditor.js +1 -1
  288. package/dist/agents/64-analytics-tracker-tester.d.ts +2 -2
  289. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -1
  290. package/dist/agents/64-analytics-tracker-tester.js +8 -4
  291. package/dist/agents/64-analytics-tracker-tester.js.map +1 -1
  292. package/dist/agents/65-gdpr-compliance-tester.d.ts +2 -2
  293. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -1
  294. package/dist/agents/65-gdpr-compliance-tester.js +55 -40
  295. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -1
  296. package/dist/agents/66-soc2-control-validator.d.ts +2 -2
  297. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -1
  298. package/dist/agents/66-soc2-control-validator.js +29 -21
  299. package/dist/agents/66-soc2-control-validator.js.map +1 -1
  300. package/dist/agents/67-wcag-aaa-tester.d.ts +2 -2
  301. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -1
  302. package/dist/agents/67-wcag-aaa-tester.js +12 -6
  303. package/dist/agents/67-wcag-aaa-tester.js.map +1 -1
  304. package/dist/agents/68-dead-code-detector.d.ts +2 -2
  305. package/dist/agents/68-dead-code-detector.d.ts.map +1 -1
  306. package/dist/agents/68-dead-code-detector.js +6 -3
  307. package/dist/agents/68-dead-code-detector.js.map +1 -1
  308. package/dist/agents/69-type-safety-auditor.d.ts +2 -2
  309. package/dist/agents/69-type-safety-auditor.js +1 -1
  310. package/dist/agents/70-complexity-analyzer.d.ts +2 -2
  311. package/dist/agents/70-complexity-analyzer.js +1 -1
  312. package/dist/agents/71-unit-testing-agent.d.ts +15 -0
  313. package/dist/agents/71-unit-testing-agent.d.ts.map +1 -0
  314. package/dist/agents/71-unit-testing-agent.js +220 -0
  315. package/dist/agents/71-unit-testing-agent.js.map +1 -0
  316. package/dist/agents/72-integration-testing-agent.d.ts +13 -0
  317. package/dist/agents/72-integration-testing-agent.d.ts.map +1 -0
  318. package/dist/agents/72-integration-testing-agent.js +243 -0
  319. package/dist/agents/72-integration-testing-agent.js.map +1 -0
  320. package/dist/agents/73-system-testing-agent.d.ts +11 -0
  321. package/dist/agents/73-system-testing-agent.d.ts.map +1 -0
  322. package/dist/agents/73-system-testing-agent.js +175 -0
  323. package/dist/agents/73-system-testing-agent.js.map +1 -0
  324. package/dist/agents/74-acceptance-testing-agent.d.ts +13 -0
  325. package/dist/agents/74-acceptance-testing-agent.d.ts.map +1 -0
  326. package/dist/agents/74-acceptance-testing-agent.js +254 -0
  327. package/dist/agents/74-acceptance-testing-agent.js.map +1 -0
  328. package/dist/agents/75-sanity-testing-agent.d.ts +15 -0
  329. package/dist/agents/75-sanity-testing-agent.d.ts.map +1 -0
  330. package/dist/agents/75-sanity-testing-agent.js +240 -0
  331. package/dist/agents/75-sanity-testing-agent.js.map +1 -0
  332. package/dist/agents/76-regression-testing-agent.d.ts +14 -0
  333. package/dist/agents/76-regression-testing-agent.d.ts.map +1 -0
  334. package/dist/agents/76-regression-testing-agent.js +230 -0
  335. package/dist/agents/76-regression-testing-agent.js.map +1 -0
  336. package/dist/agents/77-browser-load-testing-agent.d.ts +11 -0
  337. package/dist/agents/77-browser-load-testing-agent.d.ts.map +1 -0
  338. package/dist/agents/77-browser-load-testing-agent.js +128 -0
  339. package/dist/agents/77-browser-load-testing-agent.js.map +1 -0
  340. package/dist/agents/78-stress-testing-agent.d.ts +11 -0
  341. package/dist/agents/78-stress-testing-agent.d.ts.map +1 -0
  342. package/dist/agents/78-stress-testing-agent.js +146 -0
  343. package/dist/agents/78-stress-testing-agent.js.map +1 -0
  344. package/dist/agents/79-endurance-testing-agent.d.ts +12 -0
  345. package/dist/agents/79-endurance-testing-agent.d.ts.map +1 -0
  346. package/dist/agents/79-endurance-testing-agent.js +165 -0
  347. package/dist/agents/79-endurance-testing-agent.js.map +1 -0
  348. package/dist/agents/80-usability-testing-agent.d.ts +11 -0
  349. package/dist/agents/80-usability-testing-agent.d.ts.map +1 -0
  350. package/dist/agents/80-usability-testing-agent.js +196 -0
  351. package/dist/agents/80-usability-testing-agent.js.map +1 -0
  352. package/dist/agents/81-compatibility-testing-agent.d.ts +11 -0
  353. package/dist/agents/81-compatibility-testing-agent.d.ts.map +1 -0
  354. package/dist/agents/81-compatibility-testing-agent.js +224 -0
  355. package/dist/agents/81-compatibility-testing-agent.js.map +1 -0
  356. package/dist/agents/82-exploratory-testing-agent.d.ts +14 -0
  357. package/dist/agents/82-exploratory-testing-agent.d.ts.map +1 -0
  358. package/dist/agents/82-exploratory-testing-agent.js +345 -0
  359. package/dist/agents/82-exploratory-testing-agent.js.map +1 -0
  360. package/dist/agents/83-static-analysis-agent.d.ts +14 -0
  361. package/dist/agents/83-static-analysis-agent.d.ts.map +1 -0
  362. package/dist/agents/83-static-analysis-agent.js +261 -0
  363. package/dist/agents/83-static-analysis-agent.js.map +1 -0
  364. package/dist/agents/84-governance-testing-agent.d.ts +28 -0
  365. package/dist/agents/84-governance-testing-agent.d.ts.map +1 -0
  366. package/dist/agents/84-governance-testing-agent.js +591 -0
  367. package/dist/agents/84-governance-testing-agent.js.map +1 -0
  368. package/dist/agents/85-stagehand-agent.d.ts +22 -0
  369. package/dist/agents/85-stagehand-agent.d.ts.map +1 -0
  370. package/dist/agents/85-stagehand-agent.js +81 -0
  371. package/dist/agents/85-stagehand-agent.js.map +1 -0
  372. package/dist/agents/86-browser-use-agent.d.ts +31 -0
  373. package/dist/agents/86-browser-use-agent.d.ts.map +1 -0
  374. package/dist/agents/86-browser-use-agent.js +121 -0
  375. package/dist/agents/86-browser-use-agent.js.map +1 -0
  376. package/dist/agents/87-connection-mapper.d.ts +93 -0
  377. package/dist/agents/87-connection-mapper.d.ts.map +1 -0
  378. package/dist/agents/87-connection-mapper.js +658 -0
  379. package/dist/agents/87-connection-mapper.js.map +1 -0
  380. package/dist/agents/88-localhost-walkthrough.d.ts +272 -0
  381. package/dist/agents/88-localhost-walkthrough.d.ts.map +1 -0
  382. package/dist/agents/88-localhost-walkthrough.js +1203 -0
  383. package/dist/agents/88-localhost-walkthrough.js.map +1 -0
  384. package/dist/agents/89-repair-retest.d.ts +63 -0
  385. package/dist/agents/89-repair-retest.d.ts.map +1 -0
  386. package/dist/agents/89-repair-retest.js +227 -0
  387. package/dist/agents/89-repair-retest.js.map +1 -0
  388. package/dist/agents/90-response-shape-validator.d.ts +35 -0
  389. package/dist/agents/90-response-shape-validator.d.ts.map +1 -0
  390. package/dist/agents/90-response-shape-validator.js +156 -0
  391. package/dist/agents/90-response-shape-validator.js.map +1 -0
  392. package/dist/agents/91-boundary-fuzzer.d.ts +99 -0
  393. package/dist/agents/91-boundary-fuzzer.d.ts.map +1 -0
  394. package/dist/agents/91-boundary-fuzzer.js +0 -0
  395. package/dist/agents/91-boundary-fuzzer.js.map +1 -0
  396. package/dist/agents/92-repair-simulator.d.ts +89 -0
  397. package/dist/agents/92-repair-simulator.d.ts.map +1 -0
  398. package/dist/agents/92-repair-simulator.js +401 -0
  399. package/dist/agents/92-repair-simulator.js.map +1 -0
  400. package/dist/agents/93-env-var-auditor.d.ts +64 -0
  401. package/dist/agents/93-env-var-auditor.d.ts.map +1 -0
  402. package/dist/agents/93-env-var-auditor.js +435 -0
  403. package/dist/agents/93-env-var-auditor.js.map +1 -0
  404. package/dist/agents/94-schema-validator.d.ts +148 -0
  405. package/dist/agents/94-schema-validator.d.ts.map +1 -0
  406. package/dist/agents/94-schema-validator.js +567 -0
  407. package/dist/agents/94-schema-validator.js.map +1 -0
  408. package/dist/agents/95-contract-drift.d.ts +87 -0
  409. package/dist/agents/95-contract-drift.d.ts.map +1 -0
  410. package/dist/agents/95-contract-drift.js +335 -0
  411. package/dist/agents/95-contract-drift.js.map +1 -0
  412. package/dist/agents/96-cookie-security-auditor.d.ts +86 -0
  413. package/dist/agents/96-cookie-security-auditor.d.ts.map +1 -0
  414. package/dist/agents/96-cookie-security-auditor.js +339 -0
  415. package/dist/agents/96-cookie-security-auditor.js.map +1 -0
  416. package/dist/agents/97-healthcheck-validator.d.ts +62 -0
  417. package/dist/agents/97-healthcheck-validator.d.ts.map +1 -0
  418. package/dist/agents/97-healthcheck-validator.js +204 -0
  419. package/dist/agents/97-healthcheck-validator.js.map +1 -0
  420. package/dist/agents/98-cors-csp-auditor.d.ts +70 -0
  421. package/dist/agents/98-cors-csp-auditor.d.ts.map +1 -0
  422. package/dist/agents/98-cors-csp-auditor.js +308 -0
  423. package/dist/agents/98-cors-csp-auditor.js.map +1 -0
  424. package/dist/agents/99-logging-hygiene-auditor.d.ts +67 -0
  425. package/dist/agents/99-logging-hygiene-auditor.d.ts.map +1 -0
  426. package/dist/agents/99-logging-hygiene-auditor.js +325 -0
  427. package/dist/agents/99-logging-hygiene-auditor.js.map +1 -0
  428. package/dist/agents/base-agent.d.ts +75 -3
  429. package/dist/agents/base-agent.d.ts.map +1 -1
  430. package/dist/agents/base-agent.js +112 -1
  431. package/dist/agents/base-agent.js.map +1 -1
  432. package/dist/agents/browser-use-client.d.ts +68 -0
  433. package/dist/agents/browser-use-client.d.ts.map +1 -0
  434. package/dist/agents/browser-use-client.js +92 -0
  435. package/dist/agents/browser-use-client.js.map +1 -0
  436. package/dist/agents/lib/source-scan.d.ts +53 -0
  437. package/dist/agents/lib/source-scan.d.ts.map +1 -0
  438. package/dist/agents/lib/source-scan.js +279 -0
  439. package/dist/agents/lib/source-scan.js.map +1 -0
  440. package/dist/agents/registry.d.ts +27 -8
  441. package/dist/agents/registry.d.ts.map +1 -1
  442. package/dist/agents/registry.js +365 -151
  443. package/dist/agents/registry.js.map +1 -1
  444. package/dist/agents/stagehand-runner.d.ts +104 -0
  445. package/dist/agents/stagehand-runner.d.ts.map +1 -0
  446. package/dist/agents/stagehand-runner.js +153 -0
  447. package/dist/agents/stagehand-runner.js.map +1 -0
  448. package/dist/bridge/agent-registry.d.ts +21 -0
  449. package/dist/bridge/agent-registry.d.ts.map +1 -0
  450. package/dist/bridge/agent-registry.js +224 -0
  451. package/dist/bridge/agent-registry.js.map +1 -0
  452. package/dist/bridge/api-contract-reader.d.ts +55 -0
  453. package/dist/bridge/api-contract-reader.d.ts.map +1 -0
  454. package/dist/bridge/api-contract-reader.js +103 -0
  455. package/dist/bridge/api-contract-reader.js.map +1 -0
  456. package/dist/bridge/compliance-reader.d.ts +47 -0
  457. package/dist/bridge/compliance-reader.d.ts.map +1 -0
  458. package/dist/bridge/compliance-reader.js +91 -0
  459. package/dist/bridge/compliance-reader.js.map +1 -0
  460. package/dist/bridge/data-integrity-reader.d.ts +77 -0
  461. package/dist/bridge/data-integrity-reader.d.ts.map +1 -0
  462. package/dist/bridge/data-integrity-reader.js +110 -0
  463. package/dist/bridge/data-integrity-reader.js.map +1 -0
  464. package/dist/bridge/design-reader.d.ts +51 -0
  465. package/dist/bridge/design-reader.d.ts.map +1 -0
  466. package/dist/bridge/design-reader.js +105 -0
  467. package/dist/bridge/design-reader.js.map +1 -0
  468. package/dist/bridge/file-scanner.d.ts +21 -0
  469. package/dist/bridge/file-scanner.d.ts.map +1 -0
  470. package/dist/bridge/file-scanner.js +117 -0
  471. package/dist/bridge/file-scanner.js.map +1 -0
  472. package/dist/bridge/finding-normalize.d.ts +24 -0
  473. package/dist/bridge/finding-normalize.d.ts.map +1 -0
  474. package/dist/bridge/finding-normalize.js +46 -0
  475. package/dist/bridge/finding-normalize.js.map +1 -0
  476. package/dist/bridge/http-client.d.ts +44 -0
  477. package/dist/bridge/http-client.d.ts.map +1 -0
  478. package/dist/bridge/http-client.js +130 -0
  479. package/dist/bridge/http-client.js.map +1 -0
  480. package/dist/bridge/knowledge-reader.d.ts +10 -0
  481. package/dist/bridge/knowledge-reader.d.ts.map +1 -0
  482. package/dist/bridge/knowledge-reader.js +46 -0
  483. package/dist/bridge/knowledge-reader.js.map +1 -0
  484. package/dist/bridge/loop-engine-reader.d.ts +77 -0
  485. package/dist/bridge/loop-engine-reader.d.ts.map +1 -0
  486. package/dist/bridge/loop-engine-reader.js +73 -0
  487. package/dist/bridge/loop-engine-reader.js.map +1 -0
  488. package/dist/bridge/playwright-pool.d.ts +33 -0
  489. package/dist/bridge/playwright-pool.d.ts.map +1 -0
  490. package/dist/bridge/playwright-pool.js +89 -0
  491. package/dist/bridge/playwright-pool.js.map +1 -0
  492. package/dist/bridge/rate-limiter.d.ts +40 -0
  493. package/dist/bridge/rate-limiter.d.ts.map +1 -0
  494. package/dist/bridge/rate-limiter.js +33 -0
  495. package/dist/bridge/rate-limiter.js.map +1 -0
  496. package/dist/bridge/reliability-reader.d.ts +67 -0
  497. package/dist/bridge/reliability-reader.d.ts.map +1 -0
  498. package/dist/bridge/reliability-reader.js +146 -0
  499. package/dist/bridge/reliability-reader.js.map +1 -0
  500. package/dist/bridge/router.d.ts +26 -0
  501. package/dist/bridge/router.d.ts.map +1 -0
  502. package/dist/bridge/router.js +137 -0
  503. package/dist/bridge/router.js.map +1 -0
  504. package/dist/bridge/run-stream.d.ts +47 -0
  505. package/dist/bridge/run-stream.d.ts.map +1 -0
  506. package/dist/bridge/run-stream.js +67 -0
  507. package/dist/bridge/run-stream.js.map +1 -0
  508. package/dist/bridge/runs-reader.d.ts +41 -0
  509. package/dist/bridge/runs-reader.d.ts.map +1 -0
  510. package/dist/bridge/runs-reader.js +185 -0
  511. package/dist/bridge/runs-reader.js.map +1 -0
  512. package/dist/bridge/sentinel-reader.d.ts +55 -0
  513. package/dist/bridge/sentinel-reader.d.ts.map +1 -0
  514. package/dist/bridge/sentinel-reader.js +88 -0
  515. package/dist/bridge/sentinel-reader.js.map +1 -0
  516. package/dist/bridge/server.d.ts +83 -0
  517. package/dist/bridge/server.d.ts.map +1 -0
  518. package/dist/bridge/server.js +1103 -0
  519. package/dist/bridge/server.js.map +1 -0
  520. package/dist/bridge/shell-executor.d.ts +49 -0
  521. package/dist/bridge/shell-executor.d.ts.map +1 -0
  522. package/dist/bridge/shell-executor.js +181 -0
  523. package/dist/bridge/shell-executor.js.map +1 -0
  524. package/dist/bridge/tech-debt-reader.d.ts +57 -0
  525. package/dist/bridge/tech-debt-reader.d.ts.map +1 -0
  526. package/dist/bridge/tech-debt-reader.js +119 -0
  527. package/dist/bridge/tech-debt-reader.js.map +1 -0
  528. package/dist/bridge/types.d.ts +63 -0
  529. package/dist/bridge/types.d.ts.map +1 -0
  530. package/dist/bridge/types.js +7 -0
  531. package/dist/bridge/types.js.map +1 -0
  532. package/dist/clients/agent-mvp.d.ts +68 -0
  533. package/dist/clients/agent-mvp.d.ts.map +1 -0
  534. package/dist/clients/agent-mvp.js +102 -0
  535. package/dist/clients/agent-mvp.js.map +1 -0
  536. package/dist/clients/llm-council.d.ts +47 -0
  537. package/dist/clients/llm-council.d.ts.map +1 -0
  538. package/dist/clients/llm-council.js +52 -0
  539. package/dist/clients/llm-council.js.map +1 -0
  540. package/dist/clients/total-recall.d.ts +37 -0
  541. package/dist/clients/total-recall.d.ts.map +1 -0
  542. package/dist/clients/total-recall.js +239 -0
  543. package/dist/clients/total-recall.js.map +1 -0
  544. package/dist/core/agent-contract.d.ts +21 -0
  545. package/dist/core/agent-contract.d.ts.map +1 -0
  546. package/dist/core/agent-contract.js +18 -0
  547. package/dist/core/agent-contract.js.map +1 -0
  548. package/dist/core/api-contract/api-contract-validator.d.ts +178 -0
  549. package/dist/core/api-contract/api-contract-validator.d.ts.map +1 -0
  550. package/dist/core/api-contract/api-contract-validator.js +796 -0
  551. package/dist/core/api-contract/api-contract-validator.js.map +1 -0
  552. package/dist/core/api-contract/index.d.ts +16 -0
  553. package/dist/core/api-contract/index.d.ts.map +1 -0
  554. package/dist/core/api-contract/index.js +24 -0
  555. package/dist/core/api-contract/index.js.map +1 -0
  556. package/dist/core/api-contract/types.d.ts +235 -0
  557. package/dist/core/api-contract/types.d.ts.map +1 -0
  558. package/dist/core/api-contract/types.js +27 -0
  559. package/dist/core/api-contract/types.js.map +1 -0
  560. package/dist/core/blackboard/blackboard.d.ts +34 -0
  561. package/dist/core/blackboard/blackboard.d.ts.map +1 -0
  562. package/dist/core/blackboard/blackboard.js +133 -0
  563. package/dist/core/blackboard/blackboard.js.map +1 -0
  564. package/dist/core/blackboard/coordination.d.ts +27 -0
  565. package/dist/core/blackboard/coordination.d.ts.map +1 -0
  566. package/dist/core/blackboard/coordination.js +31 -0
  567. package/dist/core/blackboard/coordination.js.map +1 -0
  568. package/dist/core/blackboard/direct-channel.d.ts +26 -0
  569. package/dist/core/blackboard/direct-channel.d.ts.map +1 -0
  570. package/dist/core/blackboard/direct-channel.js +26 -0
  571. package/dist/core/blackboard/direct-channel.js.map +1 -0
  572. package/dist/core/blackboard/index.d.ts +10 -0
  573. package/dist/core/blackboard/index.d.ts.map +1 -0
  574. package/dist/core/blackboard/index.js +4 -0
  575. package/dist/core/blackboard/index.js.map +1 -0
  576. package/dist/core/blackboard/types.d.ts +36 -0
  577. package/dist/core/blackboard/types.d.ts.map +1 -0
  578. package/dist/core/blackboard/types.js +2 -0
  579. package/dist/core/blackboard/types.js.map +1 -0
  580. package/dist/core/canvas/schema.d.ts +81 -0
  581. package/dist/core/canvas/schema.d.ts.map +1 -0
  582. package/dist/core/canvas/schema.js +144 -0
  583. package/dist/core/canvas/schema.js.map +1 -0
  584. package/dist/core/canvas/store.d.ts +41 -0
  585. package/dist/core/canvas/store.d.ts.map +1 -0
  586. package/dist/core/canvas/store.js +121 -0
  587. package/dist/core/canvas/store.js.map +1 -0
  588. package/dist/core/ci-output.d.ts +1 -1
  589. package/dist/core/ci-output.d.ts.map +1 -1
  590. package/dist/core/ci-output.js +2 -0
  591. package/dist/core/ci-output.js.map +1 -1
  592. package/dist/core/cli.d.ts +15 -1
  593. package/dist/core/cli.d.ts.map +1 -1
  594. package/dist/core/cli.js +416 -35
  595. package/dist/core/cli.js.map +1 -1
  596. package/dist/core/compliance/auditor.d.ts +119 -0
  597. package/dist/core/compliance/auditor.d.ts.map +1 -0
  598. package/dist/core/compliance/auditor.js +577 -0
  599. package/dist/core/compliance/auditor.js.map +1 -0
  600. package/dist/core/compliance/index.d.ts +11 -0
  601. package/dist/core/compliance/index.d.ts.map +1 -0
  602. package/dist/core/compliance/index.js +10 -0
  603. package/dist/core/compliance/index.js.map +1 -0
  604. package/dist/core/compliance/types.d.ts +174 -0
  605. package/dist/core/compliance/types.d.ts.map +1 -0
  606. package/dist/core/compliance/types.js +12 -0
  607. package/dist/core/compliance/types.js.map +1 -0
  608. package/dist/core/conductor/conductor.d.ts +37 -0
  609. package/dist/core/conductor/conductor.d.ts.map +1 -0
  610. package/dist/core/conductor/conductor.js +96 -0
  611. package/dist/core/conductor/conductor.js.map +1 -0
  612. package/dist/core/conductor/index.d.ts +9 -0
  613. package/dist/core/conductor/index.d.ts.map +1 -0
  614. package/dist/core/conductor/index.js +3 -0
  615. package/dist/core/conductor/index.js.map +1 -0
  616. package/dist/core/conductor/model-router.d.ts +17 -0
  617. package/dist/core/conductor/model-router.d.ts.map +1 -0
  618. package/dist/core/conductor/model-router.js +29 -0
  619. package/dist/core/conductor/model-router.js.map +1 -0
  620. package/dist/core/conductor/types.d.ts +33 -0
  621. package/dist/core/conductor/types.d.ts.map +1 -0
  622. package/dist/core/conductor/types.js +2 -0
  623. package/dist/core/conductor/types.js.map +1 -0
  624. package/dist/core/config.d.ts +148 -1
  625. package/dist/core/config.d.ts.map +1 -1
  626. package/dist/core/config.js +53 -4
  627. package/dist/core/config.js.map +1 -1
  628. package/dist/core/data-integrity/data-integrity.d.ts +291 -0
  629. package/dist/core/data-integrity/data-integrity.d.ts.map +1 -0
  630. package/dist/core/data-integrity/data-integrity.js +892 -0
  631. package/dist/core/data-integrity/data-integrity.js.map +1 -0
  632. package/dist/core/data-integrity/index.d.ts +16 -0
  633. package/dist/core/data-integrity/index.d.ts.map +1 -0
  634. package/dist/core/data-integrity/index.js +17 -0
  635. package/dist/core/data-integrity/index.js.map +1 -0
  636. package/dist/core/data-integrity/types.d.ts +236 -0
  637. package/dist/core/data-integrity/types.d.ts.map +1 -0
  638. package/dist/core/data-integrity/types.js +14 -0
  639. package/dist/core/data-integrity/types.js.map +1 -0
  640. package/dist/core/disaster-recovery/index.d.ts +13 -0
  641. package/dist/core/disaster-recovery/index.d.ts.map +1 -0
  642. package/dist/core/disaster-recovery/index.js +3 -0
  643. package/dist/core/disaster-recovery/index.js.map +1 -0
  644. package/dist/core/disaster-recovery/simulator.d.ts +158 -0
  645. package/dist/core/disaster-recovery/simulator.d.ts.map +1 -0
  646. package/dist/core/disaster-recovery/simulator.js +553 -0
  647. package/dist/core/disaster-recovery/simulator.js.map +1 -0
  648. package/dist/core/disaster-recovery/types.d.ts +299 -0
  649. package/dist/core/disaster-recovery/types.d.ts.map +1 -0
  650. package/dist/core/disaster-recovery/types.js +33 -0
  651. package/dist/core/disaster-recovery/types.js.map +1 -0
  652. package/dist/core/escalation/heal-or-ask.d.ts +20 -0
  653. package/dist/core/escalation/heal-or-ask.d.ts.map +1 -0
  654. package/dist/core/escalation/heal-or-ask.js +19 -0
  655. package/dist/core/escalation/heal-or-ask.js.map +1 -0
  656. package/dist/core/escalation/index.d.ts +9 -0
  657. package/dist/core/escalation/index.d.ts.map +1 -0
  658. package/dist/core/escalation/index.js +3 -0
  659. package/dist/core/escalation/index.js.map +1 -0
  660. package/dist/core/escalation/pause-gate.d.ts +48 -0
  661. package/dist/core/escalation/pause-gate.d.ts.map +1 -0
  662. package/dist/core/escalation/pause-gate.js +96 -0
  663. package/dist/core/escalation/pause-gate.js.map +1 -0
  664. package/dist/core/escalation/types.d.ts +33 -0
  665. package/dist/core/escalation/types.d.ts.map +1 -0
  666. package/dist/core/escalation/types.js +9 -0
  667. package/dist/core/escalation/types.js.map +1 -0
  668. package/dist/core/evidence.d.ts +32 -1
  669. package/dist/core/evidence.d.ts.map +1 -1
  670. package/dist/core/evidence.js +99 -1
  671. package/dist/core/evidence.js.map +1 -1
  672. package/dist/core/feature-bdd/fix.d.ts +84 -0
  673. package/dist/core/feature-bdd/fix.d.ts.map +1 -0
  674. package/dist/core/feature-bdd/fix.js +121 -0
  675. package/dist/core/feature-bdd/fix.js.map +1 -0
  676. package/dist/core/feature-bdd/generate.d.ts +96 -0
  677. package/dist/core/feature-bdd/generate.d.ts.map +1 -0
  678. package/dist/core/feature-bdd/generate.js +228 -0
  679. package/dist/core/feature-bdd/generate.js.map +1 -0
  680. package/dist/core/feature-bdd/llm-provider.d.ts +92 -0
  681. package/dist/core/feature-bdd/llm-provider.d.ts.map +1 -0
  682. package/dist/core/feature-bdd/llm-provider.js +187 -0
  683. package/dist/core/feature-bdd/llm-provider.js.map +1 -0
  684. package/dist/core/feature-bdd/run.d.ts +56 -0
  685. package/dist/core/feature-bdd/run.d.ts.map +1 -0
  686. package/dist/core/feature-bdd/run.js +175 -0
  687. package/dist/core/feature-bdd/run.js.map +1 -0
  688. package/dist/core/feature-bdd/schema.d.ts +111 -0
  689. package/dist/core/feature-bdd/schema.d.ts.map +1 -0
  690. package/dist/core/feature-bdd/schema.js +272 -0
  691. package/dist/core/feature-bdd/schema.js.map +1 -0
  692. package/dist/core/feature-bdd/store.d.ts +145 -0
  693. package/dist/core/feature-bdd/store.d.ts.map +1 -0
  694. package/dist/core/feature-bdd/store.js +470 -0
  695. package/dist/core/feature-bdd/store.js.map +1 -0
  696. package/dist/core/finding-correlation.d.ts +55 -0
  697. package/dist/core/finding-correlation.d.ts.map +1 -0
  698. package/dist/core/finding-correlation.js +96 -0
  699. package/dist/core/finding-correlation.js.map +1 -0
  700. package/dist/core/fix-loop.d.ts +20 -1
  701. package/dist/core/fix-loop.d.ts.map +1 -1
  702. package/dist/core/fix-loop.js +34 -0
  703. package/dist/core/fix-loop.js.map +1 -1
  704. package/dist/core/governance/calibration.d.ts +31 -0
  705. package/dist/core/governance/calibration.d.ts.map +1 -0
  706. package/dist/core/governance/calibration.js +78 -0
  707. package/dist/core/governance/calibration.js.map +1 -0
  708. package/dist/core/governance/degradation.d.ts +35 -0
  709. package/dist/core/governance/degradation.d.ts.map +1 -0
  710. package/dist/core/governance/degradation.js +25 -0
  711. package/dist/core/governance/degradation.js.map +1 -0
  712. package/dist/core/governance/ethical-constraint.d.ts +55 -0
  713. package/dist/core/governance/ethical-constraint.d.ts.map +1 -0
  714. package/dist/core/governance/ethical-constraint.js +98 -0
  715. package/dist/core/governance/ethical-constraint.js.map +1 -0
  716. package/dist/core/governance/index.d.ts +9 -0
  717. package/dist/core/governance/index.d.ts.map +1 -0
  718. package/dist/core/governance/index.js +9 -0
  719. package/dist/core/governance/index.js.map +1 -0
  720. package/dist/core/harness/audit-log.d.ts +12 -0
  721. package/dist/core/harness/audit-log.d.ts.map +1 -0
  722. package/dist/core/harness/audit-log.js +62 -0
  723. package/dist/core/harness/audit-log.js.map +1 -0
  724. package/dist/core/harness/authorization.d.ts +24 -0
  725. package/dist/core/harness/authorization.d.ts.map +1 -0
  726. package/dist/core/harness/authorization.js +48 -0
  727. package/dist/core/harness/authorization.js.map +1 -0
  728. package/dist/core/harness/harness.d.ts +64 -0
  729. package/dist/core/harness/harness.d.ts.map +1 -0
  730. package/dist/core/harness/harness.js +188 -0
  731. package/dist/core/harness/harness.js.map +1 -0
  732. package/dist/core/harness/index.d.ts +10 -0
  733. package/dist/core/harness/index.d.ts.map +1 -0
  734. package/dist/core/harness/index.js +4 -0
  735. package/dist/core/harness/index.js.map +1 -0
  736. package/dist/core/harness/types.d.ts +88 -0
  737. package/dist/core/harness/types.d.ts.map +1 -0
  738. package/dist/core/harness/types.js +2 -0
  739. package/dist/core/harness/types.js.map +1 -0
  740. package/dist/core/health-check.d.ts +6 -0
  741. package/dist/core/health-check.d.ts.map +1 -1
  742. package/dist/core/health-check.js +14 -2
  743. package/dist/core/health-check.js.map +1 -1
  744. package/dist/core/init.d.ts.map +1 -1
  745. package/dist/core/init.js +58 -18
  746. package/dist/core/init.js.map +1 -1
  747. package/dist/core/knowledge/cached-map.d.ts +17 -0
  748. package/dist/core/knowledge/cached-map.d.ts.map +1 -0
  749. package/dist/core/knowledge/cached-map.js +23 -0
  750. package/dist/core/knowledge/cached-map.js.map +1 -0
  751. package/dist/core/knowledge/index.d.ts +10 -0
  752. package/dist/core/knowledge/index.d.ts.map +1 -0
  753. package/dist/core/knowledge/index.js +4 -0
  754. package/dist/core/knowledge/index.js.map +1 -0
  755. package/dist/core/knowledge/system-map.d.ts +50 -0
  756. package/dist/core/knowledge/system-map.d.ts.map +1 -0
  757. package/dist/core/knowledge/system-map.js +121 -0
  758. package/dist/core/knowledge/system-map.js.map +1 -0
  759. package/dist/core/knowledge/traversal.d.ts +12 -0
  760. package/dist/core/knowledge/traversal.d.ts.map +1 -0
  761. package/dist/core/knowledge/traversal.js +37 -0
  762. package/dist/core/knowledge/traversal.js.map +1 -0
  763. package/dist/core/knowledge/types.d.ts +41 -0
  764. package/dist/core/knowledge/types.d.ts.map +1 -0
  765. package/dist/core/knowledge/types.js +2 -0
  766. package/dist/core/knowledge/types.js.map +1 -0
  767. package/dist/core/license-gen.d.ts +1 -1
  768. package/dist/core/license-gen.d.ts.map +1 -1
  769. package/dist/core/license-gen.js +10 -5
  770. package/dist/core/license-gen.js.map +1 -1
  771. package/dist/core/license.d.ts +12 -2
  772. package/dist/core/license.d.ts.map +1 -1
  773. package/dist/core/license.js +104 -28
  774. package/dist/core/license.js.map +1 -1
  775. package/dist/core/loop-engine/circuit-breaker.d.ts +24 -0
  776. package/dist/core/loop-engine/circuit-breaker.d.ts.map +1 -0
  777. package/dist/core/loop-engine/circuit-breaker.js +48 -0
  778. package/dist/core/loop-engine/circuit-breaker.js.map +1 -0
  779. package/dist/core/loop-engine/demo.d.ts +35 -0
  780. package/dist/core/loop-engine/demo.d.ts.map +1 -0
  781. package/dist/core/loop-engine/demo.js +71 -0
  782. package/dist/core/loop-engine/demo.js.map +1 -0
  783. package/dist/core/loop-engine/event-store.d.ts +8 -0
  784. package/dist/core/loop-engine/event-store.d.ts.map +1 -0
  785. package/dist/core/loop-engine/event-store.js +9 -0
  786. package/dist/core/loop-engine/event-store.js.map +1 -0
  787. package/dist/core/loop-engine/index.d.ts +11 -0
  788. package/dist/core/loop-engine/index.d.ts.map +1 -0
  789. package/dist/core/loop-engine/index.js +11 -0
  790. package/dist/core/loop-engine/index.js.map +1 -0
  791. package/dist/core/loop-engine/kernel.d.ts +66 -0
  792. package/dist/core/loop-engine/kernel.d.ts.map +1 -0
  793. package/dist/core/loop-engine/kernel.js +196 -0
  794. package/dist/core/loop-engine/kernel.js.map +1 -0
  795. package/dist/core/loop-engine/tracing.d.ts +12 -0
  796. package/dist/core/loop-engine/tracing.d.ts.map +1 -0
  797. package/dist/core/loop-engine/tracing.js +15 -0
  798. package/dist/core/loop-engine/tracing.js.map +1 -0
  799. package/dist/core/loop-engine/types.d.ts +92 -0
  800. package/dist/core/loop-engine/types.d.ts.map +1 -0
  801. package/dist/core/loop-engine/types.js +21 -0
  802. package/dist/core/loop-engine/types.js.map +1 -0
  803. package/dist/core/messages.d.ts +1 -1
  804. package/dist/core/messages.d.ts.map +1 -1
  805. package/dist/core/messages.js +101 -1
  806. package/dist/core/messages.js.map +1 -1
  807. package/dist/core/orchestrator.d.ts +87 -7
  808. package/dist/core/orchestrator.d.ts.map +1 -1
  809. package/dist/core/orchestrator.js +399 -33
  810. package/dist/core/orchestrator.js.map +1 -1
  811. package/dist/core/phase-gate.d.ts +2 -2
  812. package/dist/core/quality-score/calculator.d.ts +125 -0
  813. package/dist/core/quality-score/calculator.d.ts.map +1 -0
  814. package/dist/core/quality-score/calculator.js +489 -0
  815. package/dist/core/quality-score/calculator.js.map +1 -0
  816. package/dist/core/quality-score/from-run.d.ts +27 -0
  817. package/dist/core/quality-score/from-run.d.ts.map +1 -0
  818. package/dist/core/quality-score/from-run.js +64 -0
  819. package/dist/core/quality-score/from-run.js.map +1 -0
  820. package/dist/core/quality-score/index.d.ts +9 -0
  821. package/dist/core/quality-score/index.d.ts.map +1 -0
  822. package/dist/core/quality-score/index.js +9 -0
  823. package/dist/core/quality-score/index.js.map +1 -0
  824. package/dist/core/quality-score/types.d.ts +225 -0
  825. package/dist/core/quality-score/types.d.ts.map +1 -0
  826. package/dist/core/quality-score/types.js +26 -0
  827. package/dist/core/quality-score/types.js.map +1 -0
  828. package/dist/core/report-html-script.d.ts +3 -0
  829. package/dist/core/report-html-script.d.ts.map +1 -0
  830. package/dist/core/report-html-script.js +47 -0
  831. package/dist/core/report-html-script.js.map +1 -0
  832. package/dist/core/report-html-styles.d.ts +3 -0
  833. package/dist/core/report-html-styles.d.ts.map +1 -0
  834. package/dist/core/report-html-styles.js +231 -0
  835. package/dist/core/report-html-styles.js.map +1 -0
  836. package/dist/core/report-html.d.ts +1 -1
  837. package/dist/core/report-html.d.ts.map +1 -1
  838. package/dist/core/report-html.js +5 -280
  839. package/dist/core/report-html.js.map +1 -1
  840. package/dist/core/report-upload.d.ts +8 -0
  841. package/dist/core/report-upload.d.ts.map +1 -1
  842. package/dist/core/report-upload.js +17 -4
  843. package/dist/core/report-upload.js.map +1 -1
  844. package/dist/core/run-counter.d.ts.map +1 -1
  845. package/dist/core/run-counter.js +25 -1
  846. package/dist/core/run-counter.js.map +1 -1
  847. package/dist/core/run-events/emitter.d.ts +112 -0
  848. package/dist/core/run-events/emitter.d.ts.map +1 -0
  849. package/dist/core/run-events/emitter.js +234 -0
  850. package/dist/core/run-events/emitter.js.map +1 -0
  851. package/dist/core/run-events/frame-sink.d.ts +24 -0
  852. package/dist/core/run-events/frame-sink.d.ts.map +1 -0
  853. package/dist/core/run-events/frame-sink.js +32 -0
  854. package/dist/core/run-events/frame-sink.js.map +1 -0
  855. package/dist/core/run-events/index.d.ts +7 -0
  856. package/dist/core/run-events/index.d.ts.map +1 -0
  857. package/dist/core/run-events/index.js +5 -0
  858. package/dist/core/run-events/index.js.map +1 -0
  859. package/dist/core/run-events/loop-event-sink.d.ts +56 -0
  860. package/dist/core/run-events/loop-event-sink.d.ts.map +1 -0
  861. package/dist/core/run-events/loop-event-sink.js +60 -0
  862. package/dist/core/run-events/loop-event-sink.js.map +1 -0
  863. package/dist/core/run-events/sse.d.ts +47 -0
  864. package/dist/core/run-events/sse.d.ts.map +1 -0
  865. package/dist/core/run-events/sse.js +64 -0
  866. package/dist/core/run-events/sse.js.map +1 -0
  867. package/dist/core/run-events/types.d.ts +147 -0
  868. package/dist/core/run-events/types.d.ts.map +1 -0
  869. package/dist/core/run-events/types.js +17 -0
  870. package/dist/core/run-events/types.js.map +1 -0
  871. package/dist/core/run-mode/capture.d.ts +37 -0
  872. package/dist/core/run-mode/capture.d.ts.map +1 -0
  873. package/dist/core/run-mode/capture.js +43 -0
  874. package/dist/core/run-mode/capture.js.map +1 -0
  875. package/dist/core/run-mode/index.d.ts +9 -0
  876. package/dist/core/run-mode/index.d.ts.map +1 -0
  877. package/dist/core/run-mode/index.js +3 -0
  878. package/dist/core/run-mode/index.js.map +1 -0
  879. package/dist/core/run-mode/run-mode.d.ts +35 -0
  880. package/dist/core/run-mode/run-mode.d.ts.map +1 -0
  881. package/dist/core/run-mode/run-mode.js +51 -0
  882. package/dist/core/run-mode/run-mode.js.map +1 -0
  883. package/dist/core/run-mode/types.d.ts +36 -0
  884. package/dist/core/run-mode/types.d.ts.map +1 -0
  885. package/dist/core/run-mode/types.js +15 -0
  886. package/dist/core/run-mode/types.js.map +1 -0
  887. package/dist/core/run-quota.d.ts +22 -0
  888. package/dist/core/run-quota.d.ts.map +1 -0
  889. package/dist/core/run-quota.js +44 -0
  890. package/dist/core/run-quota.js.map +1 -0
  891. package/dist/core/security-audit/index.d.ts +9 -0
  892. package/dist/core/security-audit/index.d.ts.map +1 -0
  893. package/dist/core/security-audit/index.js +10 -0
  894. package/dist/core/security-audit/index.js.map +1 -0
  895. package/dist/core/security-audit/sentinel.d.ts +196 -0
  896. package/dist/core/security-audit/sentinel.d.ts.map +1 -0
  897. package/dist/core/security-audit/sentinel.js +725 -0
  898. package/dist/core/security-audit/sentinel.js.map +1 -0
  899. package/dist/core/security-audit/types.d.ts +240 -0
  900. package/dist/core/security-audit/types.d.ts.map +1 -0
  901. package/dist/core/security-audit/types.js +42 -0
  902. package/dist/core/security-audit/types.js.map +1 -0
  903. package/dist/core/tech-debt/index.d.ts +11 -0
  904. package/dist/core/tech-debt/index.d.ts.map +1 -0
  905. package/dist/core/tech-debt/index.js +11 -0
  906. package/dist/core/tech-debt/index.js.map +1 -0
  907. package/dist/core/tech-debt/tech-debt-tracker.d.ts +46 -0
  908. package/dist/core/tech-debt/tech-debt-tracker.d.ts.map +1 -0
  909. package/dist/core/tech-debt/tech-debt-tracker.js +533 -0
  910. package/dist/core/tech-debt/tech-debt-tracker.js.map +1 -0
  911. package/dist/core/tech-debt/types.d.ts +263 -0
  912. package/dist/core/tech-debt/types.d.ts.map +1 -0
  913. package/dist/core/tech-debt/types.js +2 -0
  914. package/dist/core/tech-debt/types.js.map +1 -0
  915. package/dist/core/tester/diff-planner.d.ts +18 -0
  916. package/dist/core/tester/diff-planner.d.ts.map +1 -0
  917. package/dist/core/tester/diff-planner.js +37 -0
  918. package/dist/core/tester/diff-planner.js.map +1 -0
  919. package/dist/core/tester/honest-report.d.ts +13 -0
  920. package/dist/core/tester/honest-report.d.ts.map +1 -0
  921. package/dist/core/tester/honest-report.js +64 -0
  922. package/dist/core/tester/honest-report.js.map +1 -0
  923. package/dist/core/tester/index.d.ts +9 -0
  924. package/dist/core/tester/index.d.ts.map +1 -0
  925. package/dist/core/tester/index.js +3 -0
  926. package/dist/core/tester/index.js.map +1 -0
  927. package/dist/core/tester/types.d.ts +55 -0
  928. package/dist/core/tester/types.d.ts.map +1 -0
  929. package/dist/core/tester/types.js +8 -0
  930. package/dist/core/tester/types.js.map +1 -0
  931. package/dist/core/triggers/index.d.ts +9 -0
  932. package/dist/core/triggers/index.d.ts.map +1 -0
  933. package/dist/core/triggers/index.js +3 -0
  934. package/dist/core/triggers/index.js.map +1 -0
  935. package/dist/core/triggers/trigger-bus.d.ts +49 -0
  936. package/dist/core/triggers/trigger-bus.d.ts.map +1 -0
  937. package/dist/core/triggers/trigger-bus.js +167 -0
  938. package/dist/core/triggers/trigger-bus.js.map +1 -0
  939. package/dist/core/triggers/types.d.ts +56 -0
  940. package/dist/core/triggers/types.d.ts.map +1 -0
  941. package/dist/core/triggers/types.js +13 -0
  942. package/dist/core/triggers/types.js.map +1 -0
  943. package/dist/core/trust.d.ts +12 -0
  944. package/dist/core/trust.d.ts.map +1 -0
  945. package/dist/core/trust.js +13 -0
  946. package/dist/core/trust.js.map +1 -0
  947. package/dist/core/types.d.ts +24 -2
  948. package/dist/core/types.d.ts.map +1 -1
  949. package/dist/core/ui-ux/index.d.ts +12 -0
  950. package/dist/core/ui-ux/index.d.ts.map +1 -0
  951. package/dist/core/ui-ux/index.js +13 -0
  952. package/dist/core/ui-ux/index.js.map +1 -0
  953. package/dist/core/ui-ux/orchestrator.d.ts +206 -0
  954. package/dist/core/ui-ux/orchestrator.d.ts.map +1 -0
  955. package/dist/core/ui-ux/orchestrator.js +672 -0
  956. package/dist/core/ui-ux/orchestrator.js.map +1 -0
  957. package/dist/core/ui-ux/types.d.ts +339 -0
  958. package/dist/core/ui-ux/types.d.ts.map +1 -0
  959. package/dist/core/ui-ux/types.js +17 -0
  960. package/dist/core/ui-ux/types.js.map +1 -0
  961. package/dist/enterprise/audit-trail.d.ts +31 -0
  962. package/dist/enterprise/audit-trail.d.ts.map +1 -0
  963. package/dist/enterprise/audit-trail.js +111 -0
  964. package/dist/enterprise/audit-trail.js.map +1 -0
  965. package/dist/enterprise/sla.d.ts +26 -0
  966. package/dist/enterprise/sla.d.ts.map +1 -0
  967. package/dist/enterprise/sla.js +101 -0
  968. package/dist/enterprise/sla.js.map +1 -0
  969. package/dist/helpers/element-discovery.js +1 -1
  970. package/dist/helpers/element-discovery.js.map +1 -1
  971. package/dist/helpers/env-resolver.d.ts +2 -2
  972. package/dist/helpers/quality-gate.d.ts.map +1 -1
  973. package/dist/helpers/quality-gate.js +21 -3
  974. package/dist/helpers/quality-gate.js.map +1 -1
  975. package/dist/helpers/shape-fingerprint.d.ts +18 -0
  976. package/dist/helpers/shape-fingerprint.d.ts.map +1 -0
  977. package/dist/helpers/shape-fingerprint.js +40 -0
  978. package/dist/helpers/shape-fingerprint.js.map +1 -0
  979. package/dist/sdk/custom-agent.d.ts +51 -0
  980. package/dist/sdk/custom-agent.d.ts.map +1 -0
  981. package/dist/sdk/custom-agent.js +94 -0
  982. package/dist/sdk/custom-agent.js.map +1 -0
  983. package/dist/sdk/index.d.ts +5 -0
  984. package/dist/sdk/index.d.ts.map +1 -0
  985. package/dist/sdk/index.js +3 -0
  986. package/dist/sdk/index.js.map +1 -0
  987. package/dist/sdk/loader.d.ts +28 -0
  988. package/dist/sdk/loader.d.ts.map +1 -0
  989. package/dist/sdk/loader.js +140 -0
  990. package/dist/sdk/loader.js.map +1 -0
  991. package/package.json +46 -20
  992. package/agents/01-analyst.ts +0 -100
  993. package/agents/02-seed-architect.ts +0 -59
  994. package/agents/03-test-generator.ts +0 -191
  995. package/agents/04-unit-runner.ts +0 -160
  996. package/agents/05-browser-crawler.ts +0 -790
  997. package/agents/06-api-exerciser.ts +0 -311
  998. package/agents/07-security-scout.ts +0 -188
  999. package/agents/08-a11y-guardian.ts +0 -212
  1000. package/agents/09-healer.ts +0 -228
  1001. package/agents/10-reporter.ts +0 -266
  1002. package/agents/11-fixer.ts +0 -253
  1003. package/agents/12-ux-inspector.ts +0 -444
  1004. package/agents/13-performance-profiler.ts +0 -271
  1005. package/agents/14-data-integrity-auditor.ts +0 -417
  1006. package/agents/15-regression-sentinel.ts +0 -307
  1007. package/agents/16-chaos-agent.ts +0 -228
  1008. package/agents/17-documentation-validator.ts +0 -266
  1009. package/agents/18-integration-watchdog.ts +0 -178
  1010. package/agents/19-tenant-isolation-auditor.ts +0 -199
  1011. package/agents/20-workflow-completion-tester.ts +0 -203
  1012. package/agents/21-state-session-tester.ts +0 -262
  1013. package/agents/22-email-notification-verifier.ts +0 -244
  1014. package/agents/23-migration-tester.ts +0 -80
  1015. package/agents/24-signup-onboarding-tester.ts +0 -429
  1016. package/agents/25-crud-flow-tester.ts +0 -302
  1017. package/agents/26-form-validator.ts +0 -297
  1018. package/agents/27-search-filter-tester.ts +0 -326
  1019. package/agents/28-navigation-routing-tester.ts +0 -425
  1020. package/agents/29-responsive-interaction-tester.ts +0 -350
  1021. package/agents/30-multi-user-scenario-tester.ts +0 -319
  1022. package/agents/31-load-tester.ts +0 -134
  1023. package/agents/32-memory-leak-detector.ts +0 -194
  1024. package/agents/33-bundle-analyzer.ts +0 -132
  1025. package/agents/34-xss-scanner.ts +0 -191
  1026. package/agents/35-csrf-tester.ts +0 -82
  1027. package/agents/36-auth-fuzzer.ts +0 -194
  1028. package/agents/37-dependency-scanner.ts +0 -176
  1029. package/agents/38-secrets-scanner.ts +0 -137
  1030. package/agents/39-api-contract-tester.ts +0 -199
  1031. package/agents/40-rate-limit-tester.ts +0 -94
  1032. package/agents/41-api-pagination-tester.ts +0 -97
  1033. package/agents/42-graphql-tester.ts +0 -222
  1034. package/agents/43-data-consistency-checker.ts +0 -205
  1035. package/agents/44-backup-recovery-tester.ts +0 -152
  1036. package/agents/45-data-privacy-scanner.ts +0 -125
  1037. package/agents/46-seo-auditor.ts +0 -294
  1038. package/agents/47-social-preview-tester.ts +0 -232
  1039. package/agents/48-lighthouse-auditor.ts +0 -213
  1040. package/agents/49-i18n-tester.ts +0 -198
  1041. package/agents/50-timezone-tester.ts +0 -173
  1042. package/agents/51-error-recovery-tester.ts +0 -155
  1043. package/agents/52-offline-mode-tester.ts +0 -180
  1044. package/agents/53-graceful-degradation-tester.ts +0 -156
  1045. package/agents/54-websocket-tester.ts +0 -151
  1046. package/agents/55-realtime-sync-tester.ts +0 -194
  1047. package/agents/56-file-upload-tester.ts +0 -194
  1048. package/agents/57-export-tester.ts +0 -174
  1049. package/agents/58-payment-flow-tester.ts +0 -183
  1050. package/agents/59-ssl-tls-auditor.ts +0 -141
  1051. package/agents/60-dns-cdn-tester.ts +0 -117
  1052. package/agents/61-docker-health-checker.ts +0 -111
  1053. package/agents/62-env-config-validator.ts +0 -152
  1054. package/agents/63-log-quality-auditor.ts +0 -136
  1055. package/agents/64-analytics-tracker-tester.ts +0 -165
  1056. package/agents/65-gdpr-compliance-tester.ts +0 -215
  1057. package/agents/66-soc2-control-validator.ts +0 -210
  1058. package/agents/67-wcag-aaa-tester.ts +0 -241
  1059. package/agents/68-dead-code-detector.ts +0 -135
  1060. package/agents/69-type-safety-auditor.ts +0 -164
  1061. package/agents/70-complexity-analyzer.ts +0 -179
  1062. package/agents/__tests__/01-analyst.test.ts +0 -188
  1063. package/agents/__tests__/02-seed-architect.test.ts +0 -152
  1064. package/agents/__tests__/03-test-generator-full.test.ts +0 -321
  1065. package/agents/__tests__/03-test-generator.test.ts +0 -318
  1066. package/agents/__tests__/04-unit-runner.test.ts +0 -320
  1067. package/agents/__tests__/05-browser-crawler-beta.test.ts +0 -492
  1068. package/agents/__tests__/05-browser-crawler-release.test.ts +0 -412
  1069. package/agents/__tests__/05-browser-crawler-uat.test.ts +0 -578
  1070. package/agents/__tests__/05-browser-crawler.test.ts +0 -518
  1071. package/agents/__tests__/06-api-exerciser.test.ts +0 -619
  1072. package/agents/__tests__/07-security-scout.test.ts +0 -382
  1073. package/agents/__tests__/08-a11y-guardian.test.ts +0 -530
  1074. package/agents/__tests__/09-healer.test.ts +0 -384
  1075. package/agents/__tests__/10-reporter.test.ts +0 -366
  1076. package/agents/__tests__/11-fixer.test.ts +0 -406
  1077. package/agents/__tests__/12-ux-inspector-extended.test.ts +0 -465
  1078. package/agents/__tests__/12-ux-inspector.test.ts +0 -443
  1079. package/agents/__tests__/13-performance-profiler.test.ts +0 -411
  1080. package/agents/__tests__/14-data-integrity-auditor-extended.test.ts +0 -573
  1081. package/agents/__tests__/14-data-integrity-auditor.test.ts +0 -407
  1082. package/agents/__tests__/15-regression-sentinel.test.ts +0 -657
  1083. package/agents/__tests__/16-chaos-agent.test.ts +0 -427
  1084. package/agents/__tests__/17-documentation-validator.test.ts +0 -402
  1085. package/agents/__tests__/18-integration-watchdog.test.ts +0 -263
  1086. package/agents/__tests__/19-tenant-isolation-auditor.test.ts +0 -400
  1087. package/agents/__tests__/20-workflow-completion-tester.test.ts +0 -586
  1088. package/agents/__tests__/21-state-session-tester.test.ts +0 -374
  1089. package/agents/__tests__/22-email-notification-verifier.test.ts +0 -441
  1090. package/agents/__tests__/23-migration-tester.test.ts +0 -145
  1091. package/agents/__tests__/24-signup-onboarding-tester.test.ts +0 -274
  1092. package/agents/__tests__/25-crud-flow-tester.test.ts +0 -322
  1093. package/agents/__tests__/26-form-validator.test.ts +0 -345
  1094. package/agents/__tests__/27-search-filter-tester.test.ts +0 -311
  1095. package/agents/__tests__/28-navigation-routing-tester.test.ts +0 -328
  1096. package/agents/__tests__/29-responsive-interaction-tester.test.ts +0 -297
  1097. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +0 -328
  1098. package/agents/__tests__/31-load-tester.test.ts +0 -189
  1099. package/agents/__tests__/32-memory-leak-detector.test.ts +0 -251
  1100. package/agents/__tests__/33-bundle-analyzer.test.ts +0 -237
  1101. package/agents/__tests__/34-xss-scanner.test.ts +0 -258
  1102. package/agents/__tests__/35-csrf-tester.test.ts +0 -200
  1103. package/agents/__tests__/36-auth-fuzzer.test.ts +0 -214
  1104. package/agents/__tests__/37-dependency-scanner.test.ts +0 -266
  1105. package/agents/__tests__/38-secrets-scanner.test.ts +0 -224
  1106. package/agents/__tests__/39-api-contract-tester.test.ts +0 -312
  1107. package/agents/__tests__/40-rate-limit-tester.test.ts +0 -192
  1108. package/agents/__tests__/41-api-pagination-tester.test.ts +0 -198
  1109. package/agents/__tests__/42-graphql-tester.test.ts +0 -252
  1110. package/agents/__tests__/43-data-consistency-checker.test.ts +0 -232
  1111. package/agents/__tests__/44-backup-recovery-tester.test.ts +0 -222
  1112. package/agents/__tests__/45-data-privacy-scanner.test.ts +0 -223
  1113. package/agents/__tests__/46-seo-auditor.test.ts +0 -261
  1114. package/agents/__tests__/47-social-preview-tester.test.ts +0 -245
  1115. package/agents/__tests__/48-lighthouse-auditor.test.ts +0 -276
  1116. package/agents/__tests__/49-i18n-tester.test.ts +0 -201
  1117. package/agents/__tests__/50-timezone-tester.test.ts +0 -172
  1118. package/agents/__tests__/51-error-recovery-tester.test.ts +0 -162
  1119. package/agents/__tests__/52-offline-mode-tester.test.ts +0 -164
  1120. package/agents/__tests__/53-graceful-degradation-tester.test.ts +0 -168
  1121. package/agents/__tests__/54-websocket-tester.test.ts +0 -157
  1122. package/agents/__tests__/55-realtime-sync-tester.test.ts +0 -181
  1123. package/agents/__tests__/56-file-upload-tester.test.ts +0 -172
  1124. package/agents/__tests__/57-export-tester.test.ts +0 -169
  1125. package/agents/__tests__/58-payment-flow-tester.test.ts +0 -182
  1126. package/agents/__tests__/59-ssl-tls-auditor.test.ts +0 -179
  1127. package/agents/__tests__/60-dns-cdn-tester.test.ts +0 -176
  1128. package/agents/__tests__/61-docker-health-checker.test.ts +0 -150
  1129. package/agents/__tests__/62-env-config-validator.test.ts +0 -166
  1130. package/agents/__tests__/63-log-quality-auditor.test.ts +0 -175
  1131. package/agents/__tests__/64-analytics-tracker-tester.test.ts +0 -158
  1132. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +0 -174
  1133. package/agents/__tests__/66-soc2-control-validator.test.ts +0 -183
  1134. package/agents/__tests__/67-wcag-aaa-tester.test.ts +0 -190
  1135. package/agents/__tests__/68-dead-code-detector.test.ts +0 -174
  1136. package/agents/__tests__/69-type-safety-auditor.test.ts +0 -173
  1137. package/agents/__tests__/70-complexity-analyzer.test.ts +0 -177
  1138. package/agents/__tests__/base-agent.test.ts +0 -188
  1139. package/agents/__tests__/registry.test.ts +0 -218
  1140. package/agents/base-agent.ts +0 -77
  1141. package/agents/registry.ts +0 -277
  1142. package/baselines/api-schemas/.gitkeep +0 -0
  1143. package/baselines/performance/.gitkeep +0 -0
  1144. package/baselines/screenshots/.gitkeep +0 -0
  1145. package/core/__tests__/ci-output.test.ts +0 -430
  1146. package/core/__tests__/cli.test.ts +0 -387
  1147. package/core/__tests__/config.test.ts +0 -78
  1148. package/core/__tests__/cost-tracker.test.ts +0 -158
  1149. package/core/__tests__/evidence.test.ts +0 -265
  1150. package/core/__tests__/fix-loop.test.ts +0 -210
  1151. package/core/__tests__/health-check.test.ts +0 -44
  1152. package/core/__tests__/init.test.ts +0 -609
  1153. package/core/__tests__/integration.test.ts +0 -204
  1154. package/core/__tests__/license-gen.test.ts +0 -227
  1155. package/core/__tests__/license.test.ts +0 -326
  1156. package/core/__tests__/multi-browser.test.ts +0 -278
  1157. package/core/__tests__/orchestrator.test.ts +0 -520
  1158. package/core/__tests__/phase-gate.test.ts +0 -43
  1159. package/core/__tests__/report-html.test.ts +0 -398
  1160. package/core/__tests__/report-upload.test.ts +0 -325
  1161. package/core/__tests__/run-counter.test.ts +0 -234
  1162. package/core/ci-output.ts +0 -240
  1163. package/core/cli.ts +0 -232
  1164. package/core/config.ts +0 -178
  1165. package/core/cost-tracker.ts +0 -59
  1166. package/core/evidence.ts +0 -132
  1167. package/core/fix-loop.ts +0 -85
  1168. package/core/health-check.ts +0 -54
  1169. package/core/init.ts +0 -546
  1170. package/core/license-gen.ts +0 -212
  1171. package/core/license.ts +0 -208
  1172. package/core/messages.ts +0 -67
  1173. package/core/multi-browser.ts +0 -136
  1174. package/core/orchestrator.ts +0 -356
  1175. package/core/phase-gate.ts +0 -55
  1176. package/core/report-html.ts +0 -657
  1177. package/core/report-upload.ts +0 -188
  1178. package/core/run-counter.ts +0 -175
  1179. package/core/types.ts +0 -57
  1180. package/dist/core/multi-browser.d.ts +0 -36
  1181. package/dist/core/multi-browser.d.ts.map +0 -1
  1182. package/dist/core/multi-browser.js +0 -88
  1183. package/dist/core/multi-browser.js.map +0 -1
  1184. package/helpers/__tests__/api-client.test.ts +0 -199
  1185. package/helpers/__tests__/element-discovery.test.ts +0 -202
  1186. package/helpers/__tests__/form-filler-extended.test.ts +0 -212
  1187. package/helpers/__tests__/form-filler.test.ts +0 -99
  1188. package/helpers/__tests__/modal-handler.test.ts +0 -152
  1189. package/helpers/__tests__/navigation.test.ts +0 -214
  1190. package/helpers/__tests__/quality-gate.test.ts +0 -117
  1191. package/helpers/__tests__/screenshot.test.ts +0 -139
  1192. package/helpers/__tests__/seed-validator.test.ts +0 -114
  1193. package/helpers/api-client.ts +0 -111
  1194. package/helpers/element-discovery.ts +0 -105
  1195. package/helpers/env-resolver.ts +0 -69
  1196. package/helpers/form-filler.ts +0 -126
  1197. package/helpers/modal-handler.ts +0 -108
  1198. package/helpers/navigation.ts +0 -100
  1199. package/helpers/quality-gate.ts +0 -180
  1200. package/helpers/screenshot.ts +0 -111
  1201. package/helpers/seed-validator.ts +0 -70
@@ -0,0 +1,1273 @@
1
+ /**
2
+ * Cross-File Taint Tracker — bounded 1-hop interprocedural taint analysis.
3
+ *
4
+ * The single-file security scanners (#107 open-redirect, #108 SQLi,
5
+ * #109 path-traversal, #110 mass-assignment, #111 dynamic-eval) only fire
6
+ * when an attacker-controlled value and a dangerous sink appear in the SAME
7
+ * expression. Real code launders request data through helper functions, so
8
+ * the source and the sink live in different places:
9
+ *
10
+ * // routes/user.ts
11
+ * app.get('/u', (req, res) => res.json(runQuery(req.query.id))); // source
12
+ * // db/helpers.ts
13
+ * export function runQuery(id) { // tainted param
14
+ * return db.$queryRawUnsafe(`SELECT * FROM u WHERE id = ${id}`); // sink
15
+ * }
16
+ *
17
+ * Neither line alone trips a line-level scanner. This agent connects them:
18
+ *
19
+ * 1. Find "sink-wrapper" functions: a standalone function (declaration or
20
+ * `const fn = (…) =>`) whose body reaches a dangerous sink
21
+ * (sql / eval / command / fs-path / redirect) using one of its own
22
+ * parameters. The tainted parameter slot is recorded.
23
+ * 2. Find call sites of those wrappers anywhere in the codebase whose
24
+ * argument in the dangerous slot is request-tainted — `req`/`request`/
25
+ * `.body`/`.query`/`.params`, either directly or via a local variable
26
+ * assigned from such.
27
+ * 3. Emit a flow: source(call site) → wrapper(param) → sink.
28
+ *
29
+ * Bounded to ONE hop (source → wrapper → sink) to stay linear and
30
+ * low-false-positive: a finding requires BOTH a confirmed sink-wrapper AND a
31
+ * confirmed taint source reaching its dangerous slot. Cross-file flows (call
32
+ * site and sink in different files) are the headline; same-file 1-hop flows
33
+ * the line scanners miss are also reported.
34
+ *
35
+ * Known limitations (kept deliberately, to bound false positives): only
36
+ * standalone functions and `const fn = …` arrows are treated as wrappers
37
+ * (class/object methods are not), and taint is followed a single hop.
38
+ *
39
+ * Findings:
40
+ * - 112-taint-flow high code-bug-security
41
+ * - 112-clean / 112-summary info
42
+ *
43
+ * Persists `evidence/taint-analysis.json`. Read-only, parallel-safe, static.
44
+ */
45
+ import * as fs from 'node:fs';
46
+ import * as path from 'node:path';
47
+ import { BaseAgent } from './base-agent.js';
48
+ import { maskNonCode, isTestPath } from './lib/source-scan.js';
49
+ const SRC_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
50
+ const SKIP_DIRS = new Set([
51
+ 'node_modules', '.git', 'dist', 'build', '.next', '.nuxt', '.run', 'coverage', 'reports', 'baselines', 'evidence',
52
+ ]);
53
+ /**
54
+ * Request-input taint markers — kept in sync with the line-level scanners.
55
+ * `req`/`request` + the `.body`/`.query`/`.params` accessors also cover Koa
56
+ * (`ctx.request.body`, `ctx.params`) and Hapi (`request.payload`).
57
+ *
58
+ * The `(?!\s*\()` after the accessors disambiguates a request PROPERTY ACCESS
59
+ * (`req.query.id`, `ctx.params`, `request.body`) from a same-named METHOD CALL —
60
+ * notably TypeORM / query-builder `queryRunner.query(sql)` / `conn.params(...)`,
61
+ * which would otherwise false-positive as request input. (No real request accessor
62
+ * is invoked as `.query(`/`.params(`/`.body(`, so excluding the call form is loss-free.)
63
+ * This is the prerequisite for safely recognising NestJS class-method sink-wrappers,
64
+ * which were reverted earlier precisely because of this collision.
65
+ *
66
+ * NB: bare `args`/`payload` (GraphQL resolver args / queue payloads) false-
67
+ * positive on their pervasive non-request use (`execFile(cmd, args)`), so they
68
+ * aren't here. GraphQL resolver args are handled separately via
69
+ * `extractResolvers` (below), which gates `args` as a taint source on a
70
+ * distinctive 3/4-arg resolver signature `(parent, args, context|info, …)`.
71
+ * Queue `payload` remains a deferred gap (no equally distinctive shape).
72
+ */
73
+ export const REQUEST_RE = /\b(?:req|request)\b|\.(?:body|query|params)\b(?!\s*\(|\s*\?\.\s*\()/;
74
+ // ─────────────────────────────────────────────────────────────────────────
75
+ // Generic source helpers
76
+ // ─────────────────────────────────────────────────────────────────────────
77
+ function walk(dir, results = []) {
78
+ if (!fs.existsSync(dir))
79
+ return results;
80
+ let entries;
81
+ try {
82
+ entries = fs.readdirSync(dir, { withFileTypes: true });
83
+ }
84
+ catch {
85
+ return results;
86
+ }
87
+ for (const entry of entries) {
88
+ if (SKIP_DIRS.has(entry.name))
89
+ continue;
90
+ const full = path.join(dir, entry.name);
91
+ if (entry.isDirectory()) {
92
+ walk(full, results);
93
+ }
94
+ else if (entry.isFile() && SRC_EXTENSIONS.has(path.extname(entry.name))) {
95
+ results.push(full);
96
+ }
97
+ }
98
+ return results;
99
+ }
100
+ function relativise(absPath, root) {
101
+ return path.relative(root, absPath).split(path.sep).join('/');
102
+ }
103
+ function lineOf(content, index) {
104
+ return content.slice(0, index).split('\n').length;
105
+ }
106
+ function snippetOf(content, index) {
107
+ const start = content.lastIndexOf('\n', index) + 1;
108
+ let end = content.indexOf('\n', index);
109
+ if (end === -1)
110
+ end = content.length;
111
+ return content.slice(start, end).trim().slice(0, 160);
112
+ }
113
+ function skipWs(content, i) {
114
+ while (i < content.length && /\s/.test(content[i]))
115
+ i++;
116
+ return i;
117
+ }
118
+ /** String-aware balanced-delimiter reader. Returns the slice including delimiters. */
119
+ export function readBalanced(content, openIdx, open, close) {
120
+ if (content[openIdx] !== open)
121
+ return null;
122
+ let depth = 0;
123
+ let inString = null;
124
+ let escape = false;
125
+ for (let i = openIdx; i < content.length; i++) {
126
+ const ch = content[i];
127
+ if (escape) {
128
+ escape = false;
129
+ continue;
130
+ }
131
+ if (inString) {
132
+ if (ch === '\\')
133
+ escape = true;
134
+ else if (ch === inString)
135
+ inString = null;
136
+ continue;
137
+ }
138
+ if (ch === '"' || ch === "'" || ch === '`') {
139
+ inString = ch;
140
+ continue;
141
+ }
142
+ if (ch === open)
143
+ depth++;
144
+ else if (ch === close) {
145
+ depth--;
146
+ if (depth === 0)
147
+ return { text: content.slice(openIdx, i + 1), end: i };
148
+ }
149
+ }
150
+ return null;
151
+ }
152
+ /**
153
+ * Read an arrow-expression body (no braces) up to a top-level `;` or newline.
154
+ * With `stopAtComma`, also stop at a top-level `,` — needed for a concise arrow
155
+ * inside an argument list (`f(x => expr, other)`), whose body ends at the comma
156
+ * separating it from the next argument.
157
+ */
158
+ function readExprBody(content, start, stopAtComma = false) {
159
+ let depth = 0;
160
+ let inString = null;
161
+ let escape = false;
162
+ for (let i = start; i < content.length; i++) {
163
+ const ch = content[i];
164
+ if (escape) {
165
+ escape = false;
166
+ continue;
167
+ }
168
+ if (inString) {
169
+ if (ch === '\\')
170
+ escape = true;
171
+ else if (ch === inString)
172
+ inString = null;
173
+ continue;
174
+ }
175
+ if (ch === '"' || ch === "'" || ch === '`') {
176
+ inString = ch;
177
+ continue;
178
+ }
179
+ if (ch === '(' || ch === '[' || ch === '{')
180
+ depth++;
181
+ else if (ch === ')' || ch === ']' || ch === '}') {
182
+ if (depth === 0)
183
+ return content.slice(start, i);
184
+ depth--;
185
+ }
186
+ else if (depth === 0 && (ch === ';' || ch === '\n' || (stopAtComma && ch === ','))) {
187
+ return content.slice(start, i);
188
+ }
189
+ }
190
+ return content.slice(start);
191
+ }
192
+ /** Split a parenthesised argument list (incl. the outer parens) into top-level pieces. */
193
+ export function splitArgs(parenText) {
194
+ const inner = parenText.slice(1, -1);
195
+ if (inner.trim() === '')
196
+ return [];
197
+ const parts = [];
198
+ let depth = 0;
199
+ let inString = null;
200
+ let escape = false;
201
+ let cur = '';
202
+ for (let i = 0; i < inner.length; i++) {
203
+ const ch = inner[i];
204
+ if (escape) {
205
+ cur += ch;
206
+ escape = false;
207
+ continue;
208
+ }
209
+ if (inString) {
210
+ cur += ch;
211
+ if (ch === '\\')
212
+ escape = true;
213
+ else if (ch === inString)
214
+ inString = null;
215
+ continue;
216
+ }
217
+ if (ch === '"' || ch === "'" || ch === '`') {
218
+ inString = ch;
219
+ cur += ch;
220
+ continue;
221
+ }
222
+ if (ch === '(' || ch === '[' || ch === '{') {
223
+ depth++;
224
+ cur += ch;
225
+ }
226
+ else if (ch === ')' || ch === ']' || ch === '}') {
227
+ depth--;
228
+ cur += ch;
229
+ }
230
+ else if (ch === ',' && depth === 0) {
231
+ parts.push(cur.trim());
232
+ cur = '';
233
+ }
234
+ else {
235
+ cur += ch;
236
+ }
237
+ }
238
+ parts.push(cur.trim());
239
+ return parts;
240
+ }
241
+ /** Reduce a single parameter token to the identifier(s) it binds. */
242
+ function paramIdentifiers(token) {
243
+ let t = token.trim();
244
+ if (t.startsWith('...'))
245
+ t = t.slice(3).trim();
246
+ // strip a default value: `x = 1` → `x`
247
+ const eq = topLevelEquals(t);
248
+ if (eq !== -1)
249
+ t = t.slice(0, eq).trim();
250
+ if (t.startsWith('{') || t.startsWith('[')) {
251
+ const open = t[0];
252
+ const close = open === '{' ? '}' : ']';
253
+ // Take only the destructuring pattern, dropping any trailing `: Type` annotation.
254
+ const pat = readBalanced(t, 0, open, close);
255
+ return destructuredBindings(pat ? pat.text : t, open);
256
+ }
257
+ // strip a type annotation: `x: Foo` → `x`
258
+ const colon = t.indexOf(':');
259
+ if (colon !== -1)
260
+ t = t.slice(0, colon).trim();
261
+ // strip an optional marker: `q?` → `q` (e.g. NestJS `@Query('q') q?: string`)
262
+ if (t.endsWith('?'))
263
+ t = t.slice(0, -1).trim();
264
+ return t ? [t] : [];
265
+ }
266
+ /**
267
+ * Identifiers actually *bound* (introduced into scope) by a destructuring pattern.
268
+ * For object patterns, a `key:` to the left of a colon is a property name, not a
269
+ * binding — only the right-hand side is bound (`{ a: b }` binds `b`, not `a`;
270
+ * shorthand `{ a }` binds `a`). Array patterns bind every identifier. This keeps
271
+ * a renamed property key (`{ input: cmd }` → `cmd`, never `input`) from being
272
+ * mistaken for an in-scope taint name (adversarial-review FP-2).
273
+ */
274
+ export function destructuredBindings(pattern, kind) {
275
+ if (kind === '[') {
276
+ return [...new Set(pattern.match(/[A-Za-z_$][\w$]*/g) ?? [])];
277
+ }
278
+ const ids = [];
279
+ const re = /([A-Za-z_$][\w$]*)\s*(:)?/g;
280
+ let m;
281
+ while ((m = re.exec(pattern)) !== null) {
282
+ if (m[2] === ':')
283
+ continue; // property key (rename target) — not a binding
284
+ ids.push(m[1]);
285
+ }
286
+ return [...new Set(ids)];
287
+ }
288
+ /** Index of the first `=` that is an assignment (not `=>`, `==`, `<=`, `>=`, `!=`). */
289
+ function topLevelEquals(t) {
290
+ for (let i = 0; i < t.length; i++) {
291
+ if (t[i] !== '=')
292
+ continue;
293
+ if (t[i + 1] === '=' || t[i + 1] === '>')
294
+ continue;
295
+ if (t[i - 1] === '=' || t[i - 1] === '!' || t[i - 1] === '<' || t[i - 1] === '>')
296
+ continue;
297
+ return i;
298
+ }
299
+ return -1;
300
+ }
301
+ /** Locate a function body after its parameter list, tolerating a return-type annotation. */
302
+ function findBody(content, afterParenIdx) {
303
+ let i = skipWs(content, afterParenIdx);
304
+ if (content[i] === ':') {
305
+ i++;
306
+ let d = 0;
307
+ while (i < content.length) {
308
+ const c = content[i];
309
+ if (c === '<' || c === '(' || c === '[')
310
+ d++;
311
+ else if (c === '>' || c === ')' || c === ']')
312
+ d--;
313
+ else if (d === 0) {
314
+ if (c === '{')
315
+ break;
316
+ if (c === '=' && content[i + 1] === '>')
317
+ break;
318
+ }
319
+ i++;
320
+ }
321
+ }
322
+ if (content[i] === '{') {
323
+ const body = readBalanced(content, i, '{', '}');
324
+ return body ? { text: body.text, openIdx: i } : null;
325
+ }
326
+ if (content[i] === '=' && content[i + 1] === '>') {
327
+ const j = skipWs(content, i + 2);
328
+ if (content[j] === '{') {
329
+ const body = readBalanced(content, j, '{', '}');
330
+ return body ? { text: body.text, openIdx: j } : null;
331
+ }
332
+ return { text: readExprBody(content, j), openIdx: j };
333
+ }
334
+ return null;
335
+ }
336
+ function paramSlotsOf(parenText) {
337
+ return splitArgs(parenText).map(paramIdentifiers);
338
+ }
339
+ export function extractFunctions(content) {
340
+ const fns = [];
341
+ // function NAME(params) [: T] { ... }
342
+ const fnDecl = /(?:\bexport\s+)?(?:\bdefault\s+)?(?:\basync\s+)?\bfunction\s*\*?\s*([A-Za-z_$][\w$]*)\s*\(/g;
343
+ let m;
344
+ while ((m = fnDecl.exec(content)) !== null) {
345
+ const parenIdx = m.index + m[0].length - 1;
346
+ const params = readBalanced(content, parenIdx, '(', ')');
347
+ if (!params)
348
+ continue;
349
+ const body = findBody(content, params.end + 1);
350
+ if (!body)
351
+ continue;
352
+ fns.push({
353
+ name: m[1],
354
+ paramSlots: paramSlotsOf(params.text),
355
+ bodyText: body.text,
356
+ bodyOpenIdx: body.openIdx,
357
+ declLine: lineOf(content, m.index),
358
+ });
359
+ }
360
+ // const NAME = (params) => ... | = async (params) => ... | = function (params) { ... }
361
+ const arrowParen = /(?:\bexport\s+)?\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?(?:function\s*\*?\s*)?\(/g;
362
+ while ((m = arrowParen.exec(content)) !== null) {
363
+ const parenIdx = m.index + m[0].length - 1;
364
+ const params = readBalanced(content, parenIdx, '(', ')');
365
+ if (!params)
366
+ continue;
367
+ const body = findBody(content, params.end + 1);
368
+ if (!body)
369
+ continue;
370
+ fns.push({
371
+ name: m[1],
372
+ paramSlots: paramSlotsOf(params.text),
373
+ bodyText: body.text,
374
+ bodyOpenIdx: body.openIdx,
375
+ declLine: lineOf(content, m.index),
376
+ });
377
+ }
378
+ // const NAME = (async) IDENT => ... (single param, no parens)
379
+ const arrowSingle = /(?:\bexport\s+)?\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/g;
380
+ while ((m = arrowSingle.exec(content)) !== null) {
381
+ const arrowIdx = content.indexOf('=>', m.index + m[0].length - 2);
382
+ if (arrowIdx === -1)
383
+ continue;
384
+ const j = skipWs(content, arrowIdx + 2);
385
+ let bodyText;
386
+ let bodyOpenIdx;
387
+ if (content[j] === '{') {
388
+ const body = readBalanced(content, j, '{', '}');
389
+ if (!body)
390
+ continue;
391
+ bodyText = body.text;
392
+ bodyOpenIdx = j;
393
+ }
394
+ else {
395
+ bodyText = readExprBody(content, j);
396
+ bodyOpenIdx = j;
397
+ }
398
+ fns.push({
399
+ name: m[1],
400
+ paramSlots: [[m[2]]],
401
+ bodyText,
402
+ bodyOpenIdx,
403
+ declLine: lineOf(content, m.index),
404
+ });
405
+ }
406
+ // NB: class/object methods are NOT treated as STANDALONE wrappers here — on
407
+ // query-builder/ORM code (TypeORM's `QueryRunner.query()`) the `.query`/`.params`
408
+ // accessors collide with method names. NestJS class-method flows are handled
409
+ // separately and conservatively by `extractClasses` + the NestJS pass in
410
+ // `analyzeTaint`, which only matches same-class `this.method()` call sites (a bare
411
+ // `.find(`/`.map(` member call can never collide with an Array.prototype method).
412
+ return fns;
413
+ }
414
+ // ─────────────────────────────────────────────────────────────────────────
415
+ // NestJS class extraction (controllers / providers)
416
+ // ─────────────────────────────────────────────────────────────────────────
417
+ /**
418
+ * NestJS request-binding param decorators (names only). A param decorated with one
419
+ * of these carries client-controlled input, so its bound identifier is a taint
420
+ * source — the class-method analogue of GraphQL's resolver `args`. Distinctive
421
+ * (low false-positive, like the resolver signature gate); a bare param named
422
+ * `body`/`query`/`payload` is NOT a source without the decorator.
423
+ *
424
+ * `@MessageBody`/`@Payload` extend this to NestJS microservice + queue handlers
425
+ * (`@MessagePattern`/`@EventPattern`/`@Process`), where the deserialised message/job
426
+ * payload crosses a trust boundary just like an HTTP `@Body`. A BARE queue
427
+ * `payload`/`job.data` (plain BullMQ `new Worker(name, job => …)`, no decorator) is
428
+ * deliberately NOT a source — no distinctive non-decorator shape to gate on without
429
+ * false-positiving on pervasive non-queue `payload` use (tracked in CLEANUP_PHASE.md).
430
+ */
431
+ const NEST_SOURCE_NAMES = new Set([
432
+ 'Body', 'Query', 'Param', 'Headers', 'Req', 'Request', 'Ip', 'Session',
433
+ 'RawBody', 'UploadedFile', 'UploadedFiles', 'HostParam', 'Cookies', 'MessageBody',
434
+ 'Payload',
435
+ ]);
436
+ /** TS parameter-property modifiers stripped before reading the bound identifier. */
437
+ const PARAM_MODIFIERS = new Set(['public', 'private', 'protected', 'readonly']);
438
+ /** Method names that are really keywords/control-flow, never method definitions. */
439
+ const NON_METHOD_NAMES = new Set([
440
+ 'if', 'for', 'while', 'switch', 'catch', 'return', 'await', 'typeof', 'function',
441
+ 'new', 'do', 'else', 'yield', 'void', 'delete', 'in', 'of', 'instanceof', 'class',
442
+ 'super', 'constructor',
443
+ ]);
444
+ /**
445
+ * Strip leading decorators from a parameter token; report whether any is a source
446
+ * decorator. Decorator arguments are read paren-BALANCED, so a decorator with a
447
+ * call/object argument — `@Body(new ValidationPipe())`, `@Param('id', ParseIntPipe)` —
448
+ * is fully consumed rather than truncated at the first inner `)` (critic FN-3).
449
+ */
450
+ function parseDecoratedParam(token) {
451
+ let t = token.trim();
452
+ let isSource = false;
453
+ for (;;) {
454
+ if (t[0] !== '@')
455
+ break;
456
+ const nameMatch = t.slice(1).match(/^[A-Za-z_$][\w$]*/);
457
+ if (!nameMatch)
458
+ break;
459
+ if (NEST_SOURCE_NAMES.has(nameMatch[0]))
460
+ isSource = true;
461
+ let rest = t.slice(1 + nameMatch[0].length).replace(/^\s+/, '');
462
+ if (rest[0] === '(') {
463
+ const bal = readBalanced(rest, 0, '(', ')');
464
+ if (!bal)
465
+ break; // malformed — stop consuming
466
+ rest = rest.slice(bal.end + 1).replace(/^\s+/, '');
467
+ }
468
+ t = rest;
469
+ }
470
+ // Strip TS parameter-property modifiers (`readonly`/`private`/… — valid only on
471
+ // constructor params, defensive here) so the bound identifier is read cleanly (FN-1).
472
+ let prev;
473
+ do {
474
+ prev = t;
475
+ const w = t.match(/^([A-Za-z_$][\w$]*)\s+/);
476
+ if (w && PARAM_MODIFIERS.has(w[1]))
477
+ t = t.slice(w[0].length);
478
+ } while (t !== prev);
479
+ return { ids: paramIdentifiers(t), isSource };
480
+ }
481
+ /** Parse a (decorated) parameter list into per-slot bindings + decorator-sourced ids. */
482
+ function parseDecoratedParams(parenText) {
483
+ const slots = [];
484
+ const sourceIds = [];
485
+ for (const tok of splitArgs(parenText)) {
486
+ const { ids, isSource } = parseDecoratedParam(tok);
487
+ slots.push(ids);
488
+ if (isSource)
489
+ sourceIds.push(...ids);
490
+ }
491
+ return { slots, sourceIds };
492
+ }
493
+ /** Extract the method definitions from a class body (text incl. outer braces). */
494
+ function extractClassMethods(classBodyText, classBodyAbsIdx) {
495
+ const methods = [];
496
+ const re = /([A-Za-z_$][\w$]*)\s*\(/g;
497
+ let m;
498
+ while ((m = re.exec(classBodyText)) !== null) {
499
+ const name = m[1];
500
+ if (NON_METHOD_NAMES.has(name))
501
+ continue;
502
+ // The char before the name (skipping whitespace) must not be `.`/`?` — that
503
+ // would be a `this.foo(` / `a?.foo(` CALL, not a method definition.
504
+ let p = m.index - 1;
505
+ while (p >= 0 && /\s/.test(classBodyText[p]))
506
+ p--;
507
+ if (p >= 0 && (classBodyText[p] === '.' || classBodyText[p] === '?'))
508
+ continue;
509
+ const parenIdx = m.index + m[0].length - 1;
510
+ const params = readBalanced(classBodyText, parenIdx, '(', ')');
511
+ if (!params)
512
+ continue;
513
+ const body = findBody(classBodyText, params.end + 1);
514
+ if (!body || body.text[0] !== '{')
515
+ continue; // a real method has a brace body
516
+ const { slots, sourceIds } = parseDecoratedParams(params.text);
517
+ methods.push({
518
+ name,
519
+ paramSlots: slots,
520
+ sourceParamIds: sourceIds,
521
+ bodyText: body.text,
522
+ bodyAbsIdx: classBodyAbsIdx + body.openIdx,
523
+ bodyStart: classBodyAbsIdx + body.openIdx,
524
+ bodyEnd: classBodyAbsIdx + body.openIdx + body.text.length,
525
+ });
526
+ re.lastIndex = body.openIdx + body.text.length; // skip the body; don't re-scan its calls
527
+ }
528
+ return methods;
529
+ }
530
+ /**
531
+ * Extract class declarations and their methods. Used by the NestJS pass to find
532
+ * class-method sink-wrappers and decorator-bound request sources. Standalone
533
+ * functions remain the job of `extractFunctions`.
534
+ */
535
+ export function extractClasses(content) {
536
+ const classes = [];
537
+ const re = /\bclass\s+([A-Za-z_$][\w$]*)/g;
538
+ let m;
539
+ while ((m = re.exec(content)) !== null) {
540
+ // Walk to the class body `{`, skipping any `extends X<…>` / `implements Y, Z`.
541
+ let depth = 0;
542
+ let openIdx = -1;
543
+ for (let i = m.index + m[0].length; i < content.length; i++) {
544
+ const c = content[i];
545
+ if (c === '<' || c === '(' || c === '[')
546
+ depth++;
547
+ else if (c === '>' || c === ')' || c === ']')
548
+ depth--;
549
+ else if (depth === 0 && c === '{') {
550
+ openIdx = i;
551
+ break;
552
+ }
553
+ else if (depth === 0 && c === ';')
554
+ break;
555
+ }
556
+ if (openIdx === -1)
557
+ continue;
558
+ const body = readBalanced(content, openIdx, '{', '}');
559
+ if (!body)
560
+ continue;
561
+ classes.push({
562
+ name: m[1],
563
+ methods: extractClassMethods(body.text, openIdx),
564
+ bodyStart: openIdx,
565
+ bodyEnd: openIdx + body.text.length,
566
+ });
567
+ re.lastIndex = openIdx + body.text.length; // don't descend into nested classes twice
568
+ }
569
+ return classes;
570
+ }
571
+ // ─────────────────────────────────────────────────────────────────────────
572
+ // GraphQL resolver detection
573
+ // ─────────────────────────────────────────────────────────────────────────
574
+ /**
575
+ * Recognise the canonical GraphQL resolver signature so the resolver's `args`
576
+ * parameter can be treated as a taint source. Bare `args` was rejected as a
577
+ * global taint marker — it false-positives on `execFile(cmd, args)`; requiring
578
+ * a distinctive resolver shape removes that whole class of FP.
579
+ *
580
+ * Apollo / Yoga / graphql-tools resolvers take `(parent, args, context, info)`.
581
+ * The discriminators kept here are the *names of the later params*:
582
+ * - 4-arg shape with `context`/`ctx` at slot 2 or `info` at slot 3; or
583
+ * - 3-arg shape with `context`/`ctx`/`info` at slot 2.
584
+ * A bare 2-arg function with `args` (the original FP shape) is NOT recognised.
585
+ * NestJS `@Resolver()` class methods are not recognised here (class-method
586
+ * extraction is a separate, deferred gap).
587
+ */
588
+ const CONTEXT_PARAM_NAMES = new Set(['context', 'ctx', '_context', '_ctx']);
589
+ const INFO_PARAM_NAMES = new Set(['info', '_info']);
590
+ export function isResolverSignature(fn) {
591
+ const slots = fn.paramSlots;
592
+ if (slots.length !== 3 && slots.length !== 4)
593
+ return false;
594
+ const slotHas = (idx, names) => !!slots[idx] && slots[idx].some((n) => names.has(n));
595
+ if (slots.length === 4)
596
+ return slotHas(2, CONTEXT_PARAM_NAMES) || slotHas(3, INFO_PARAM_NAMES);
597
+ return slotHas(2, CONTEXT_PARAM_NAMES) || slotHas(2, INFO_PARAM_NAMES);
598
+ }
599
+ /**
600
+ * Pick up object-literal member functions for resolver detection. `extractFunctions`
601
+ * deliberately skips these (object/class methods as sink *wrappers* regressed FPs
602
+ * on ORM query-builders — see the note in that function). Resolvers gate on a
603
+ * strict signature, so broader extraction here is safe: the canonical Apollo
604
+ * shape is `{ Query: { user: async (parent, args, context, info) => … } }` /
605
+ * `{ user(parent, args, context, info) { … } }`, which would never be reached
606
+ * by the standalone-function extractor.
607
+ *
608
+ * Patterns picked up:
609
+ * - `KEY: async? (params) [: T] => body` (arrow-valued property)
610
+ * - `async? KEY(params) [: T] { body }` (method shorthand)
611
+ */
612
+ function extractObjectMemberFns(content) {
613
+ const fns = [];
614
+ const skipTypeAnnotationTo = (i, terminators) => {
615
+ if (content[i] !== ':')
616
+ return i;
617
+ let d = 0;
618
+ i++;
619
+ while (i < content.length) {
620
+ const c = content[i];
621
+ if (c === '<' || c === '(' || c === '[')
622
+ d++;
623
+ else if (c === '>' || c === ')' || c === ']')
624
+ d--;
625
+ else if (d === 0) {
626
+ if (c === '=' && content[i + 1] === '>')
627
+ return i;
628
+ if (terminators.has(c))
629
+ return i;
630
+ }
631
+ i++;
632
+ }
633
+ return i;
634
+ };
635
+ // `KEY : ASYNC? ( PARAMS ) [: T] => BODY`
636
+ const arrowRe = /[\s,{(]([A-Za-z_$][\w$]*)\s*:\s*(?:async\s+)?\(/g;
637
+ let m;
638
+ const ARROW_TERMINATORS = new Set([',', ';', '}', '\n']);
639
+ while ((m = arrowRe.exec(content)) !== null) {
640
+ const parenIdx = m.index + m[0].length - 1;
641
+ const params = readBalanced(content, parenIdx, '(', ')');
642
+ if (!params)
643
+ continue;
644
+ let i = skipWs(content, params.end + 1);
645
+ i = skipTypeAnnotationTo(i, ARROW_TERMINATORS);
646
+ if (content[i] !== '=' || content[i + 1] !== '>')
647
+ continue;
648
+ const bodyStart = skipWs(content, i + 2);
649
+ let bodyText;
650
+ let bodyOpenIdx;
651
+ if (content[bodyStart] === '{') {
652
+ const b = readBalanced(content, bodyStart, '{', '}');
653
+ if (!b)
654
+ continue;
655
+ bodyText = b.text;
656
+ bodyOpenIdx = bodyStart;
657
+ }
658
+ else {
659
+ bodyText = readExprBody(content, bodyStart);
660
+ bodyOpenIdx = bodyStart;
661
+ }
662
+ fns.push({
663
+ name: m[1],
664
+ paramSlots: paramSlotsOf(params.text),
665
+ bodyText,
666
+ bodyOpenIdx,
667
+ declLine: lineOf(content, m.index),
668
+ });
669
+ }
670
+ // `ASYNC? KEY ( PARAMS ) [: T] { BODY }` — object method shorthand
671
+ const methodRe = /[,{]\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*\(/g;
672
+ const METHOD_TERMINATORS = new Set([',', ';', '}', '\n']);
673
+ while ((m = methodRe.exec(content)) !== null) {
674
+ const parenIdx = m.index + m[0].length - 1;
675
+ const params = readBalanced(content, parenIdx, '(', ')');
676
+ if (!params)
677
+ continue;
678
+ let i = skipWs(content, params.end + 1);
679
+ i = skipTypeAnnotationTo(i, METHOD_TERMINATORS);
680
+ if (content[i] !== '{')
681
+ continue;
682
+ const body = readBalanced(content, i, '{', '}');
683
+ if (!body)
684
+ continue;
685
+ fns.push({
686
+ name: m[1],
687
+ paramSlots: paramSlotsOf(params.text),
688
+ bodyText: body.text,
689
+ bodyOpenIdx: i,
690
+ declLine: lineOf(content, m.index),
691
+ });
692
+ }
693
+ return fns;
694
+ }
695
+ export function extractResolvers(content) {
696
+ const out = [];
697
+ const all = [...extractFunctions(content), ...extractObjectMemberFns(content)];
698
+ for (const fn of all) {
699
+ if (!isResolverSignature(fn))
700
+ continue;
701
+ const argsNames = fn.paramSlots[1] ?? [];
702
+ if (argsNames.length === 0)
703
+ continue;
704
+ out.push({
705
+ fn,
706
+ bodyStart: fn.bodyOpenIdx,
707
+ bodyEnd: fn.bodyOpenIdx + fn.bodyText.length,
708
+ taintedNames: argsNames,
709
+ });
710
+ }
711
+ return out;
712
+ }
713
+ /**
714
+ * Inline arrow-callback scopes within `content` — `(p) => …` / `p => …` forms that
715
+ * `extractFunctions` does NOT pick up (it only finds declarations and assigned
716
+ * arrows, not anonymous callbacks like `items.map(args => …)`). Each entry gives
717
+ * the callback's bound parameter identifiers and its body offset range, so a call
718
+ * site inside the callback can be tested for parameter shadowing.
719
+ */
720
+ function inlineArrowScopes(content) {
721
+ const out = [];
722
+ let i = content.indexOf('=>');
723
+ while (i !== -1) {
724
+ // Walk back over whitespace to the end of the parameter list.
725
+ let j = i - 1;
726
+ while (j >= 0 && /\s/.test(content[j]))
727
+ j--;
728
+ let paramText = null;
729
+ if (content[j] === ')') {
730
+ // Scan back to the matching '(' (content is masked, so parens in strings are gone).
731
+ let depth = 0;
732
+ let k = j;
733
+ for (; k >= 0; k--) {
734
+ if (content[k] === ')')
735
+ depth++;
736
+ else if (content[k] === '(') {
737
+ depth--;
738
+ if (depth === 0)
739
+ break;
740
+ }
741
+ }
742
+ if (k >= 0)
743
+ paramText = content.slice(k, j + 1);
744
+ }
745
+ else if (j >= 0 && /[A-Za-z_$]/.test(content[j])) {
746
+ // Single bare identifier param: `x =>`.
747
+ let k = j;
748
+ while (k >= 0 && /[\w$]/.test(content[k]))
749
+ k--;
750
+ paramText = `(${content.slice(k + 1, j + 1)})`;
751
+ }
752
+ if (paramText !== null) {
753
+ const b = skipWs(content, i + 2);
754
+ let end;
755
+ if (content[b] === '{') {
756
+ const blk = readBalanced(content, b, '{', '}');
757
+ end = blk ? b + blk.text.length : b;
758
+ }
759
+ else {
760
+ // Concise body inside an arg list ends at the comma before the next arg.
761
+ end = b + readExprBody(content, b, true).length;
762
+ }
763
+ out.push({ paramSlots: paramSlotsOf(paramText), start: b, end });
764
+ }
765
+ i = content.indexOf('=>', i + 2);
766
+ }
767
+ return out;
768
+ }
769
+ /**
770
+ * The subset of a resolver's `taintedNames` that is NOT shadowed at `callOffset`
771
+ * by a parameter binding inside the resolver body. A nested
772
+ * `function f(args) {…}`, an assigned arrow `const g = (args) => …`, OR an inline
773
+ * callback `items.map(args => …)` all rebind `args`, so a sink call inside them
774
+ * uses the inner param — not the resolver's client input — and crediting resolver
775
+ * taint there is a false positive (adversarial-review FP-1 + Codex inline-callback
776
+ * follow-up). `callOffset` is an absolute offset into the same (masked) content
777
+ * `extractResolvers` was given.
778
+ */
779
+ /**
780
+ * The subset of `names` NOT shadowed by a nested fn/arrow scope enclosing `callOffset`.
781
+ * `bodyText` is the enclosing scope's (masked) source and `base` its absolute offset.
782
+ * Shared by the resolver and NestJS passes so both ignore a request-source name that a
783
+ * nested callback parameter rebinds — e.g. `items.map(body => this.run(body.id))`, where
784
+ * the inner `body` is the callback's local, not the request body.
785
+ */
786
+ export function unshadowedAt(bodyText, base, names, callOffset) {
787
+ if (names.length === 0)
788
+ return names;
789
+ // Shadow scopes: nested declared/assigned fns AND inline arrow callbacks.
790
+ const scopes = [];
791
+ for (const nf of extractFunctions(bodyText)) {
792
+ scopes.push({ start: base + nf.bodyOpenIdx, end: base + nf.bodyOpenIdx + nf.bodyText.length, paramSlots: nf.paramSlots });
793
+ }
794
+ for (const ar of inlineArrowScopes(bodyText)) {
795
+ scopes.push({ start: base + ar.start, end: base + ar.end, paramSlots: ar.paramSlots });
796
+ }
797
+ if (scopes.length === 0)
798
+ return names;
799
+ return names.filter((name) => {
800
+ for (const s of scopes) {
801
+ if (callOffset >= s.start && callOffset < s.end && s.paramSlots.some((slot) => slot.includes(name))) {
802
+ return false; // the call site is inside a scope that rebinds `name`
803
+ }
804
+ }
805
+ return true;
806
+ });
807
+ }
808
+ export function unshadowedResolverTaint(resolver, callOffset) {
809
+ return unshadowedAt(resolver.fn.bodyText, resolver.bodyStart, resolver.taintedNames, callOffset);
810
+ }
811
+ /**
812
+ * Sink call signatures. Each must end with `(` so the argument list can be
813
+ * read. `.exec(`/`.query(` member forms are intentionally NOT matched as
814
+ * commands (they collide with `RegExp.exec` etc.); bare `exec`/`spawn`
815
+ * (child_process via destructuring) are.
816
+ */
817
+ export const SINK_SPECS = [
818
+ { kind: 'eval', re: /(?<![.\w])eval\s*\(/g },
819
+ { kind: 'eval', re: /\bnew\s+Function\s*\(/g },
820
+ { kind: 'sql', re: /\$(?:queryRawUnsafe|executeRawUnsafe)\s*\(/g },
821
+ { kind: 'sql', re: /\.(?:query|execute|raw)\s*\(/g },
822
+ { kind: 'command', re: /(?<![.\w])exec(?:Sync|File)?\s*\(/g },
823
+ { kind: 'command', re: /(?<![.\w])spawn(?:Sync)?\s*\(/g },
824
+ {
825
+ kind: 'fs-path',
826
+ re: /\bfs(?:\.promises)?\s*\.\s*(?:readFile|readFileSync|writeFile|writeFileSync|appendFile|appendFileSync|createReadStream|createWriteStream|unlink|unlinkSync|readdir|readdirSync|open|openSync|rm|rmSync)\s*\(/g,
827
+ },
828
+ { kind: 'fs-path', re: /\.(?:sendFile|download)\s*\(/g },
829
+ { kind: 'redirect', re: /\.redirect\s*\(/g },
830
+ // SSRF: a request-tainted URL into an outbound HTTP client. Specific call
831
+ // shapes only (not a bare `.get(`) so it fires on real network sinks.
832
+ { kind: 'ssrf', re: /(?<![.\w])fetch\s*\(/g },
833
+ { kind: 'ssrf', re: /\baxios\s*(?:\.\s*(?:get|post|put|patch|delete|head|request))?\s*\(/g },
834
+ { kind: 'ssrf', re: /\b(?:https?)\s*\.\s*(?:request|get)\s*\(/g },
835
+ { kind: 'ssrf', re: /(?<![.\w])got\s*(?:\.\s*(?:get|post|put|patch|delete|head|stream))?\s*\(/g },
836
+ ];
837
+ /** True if `ident` appears as a standalone (non-member) identifier in `text`. */
838
+ export function identAppears(text, ident) {
839
+ const re = new RegExp(`(?<![.\\w])${ident.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\w])`);
840
+ return re.test(text);
841
+ }
842
+ const URL_BASE_ACCESSOR = /^(?:url|origin|href|host|hostname|protocol|port)$/;
843
+ /**
844
+ * For redirect sinks: a request param used only as a URL base — `new URL(path,
845
+ * req.url)` / `req.origin` — isn't the redirect target (the literal path is).
846
+ * Returns true when every appearance of `ident` is such a base accessor, so it
847
+ * shouldn't be treated as a tainted redirect target. A bare use or a user-input
848
+ * accessor (`.query`/`.nextUrl`/…) returns false → still flagged.
849
+ */
850
+ export function appearsOnlyAsUrlBase(text, ident) {
851
+ const re = new RegExp(`(?<![.\\w])${ident.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b\\s*(?:\\.\\s*([A-Za-z_$][\\w$]*))?`, 'g');
852
+ let m;
853
+ let appeared = false;
854
+ while ((m = re.exec(text)) !== null) {
855
+ appeared = true;
856
+ if (!m[1] || !URL_BASE_ACCESSOR.test(m[1]))
857
+ return false;
858
+ }
859
+ return appeared;
860
+ }
861
+ /** Find every (parameter-slot → sink) pair inside one function body. */
862
+ export function sinksUsingParams(fn, fileContent) {
863
+ const out = [];
864
+ const body = fn.bodyText;
865
+ const seen = new Set();
866
+ for (const spec of SINK_SPECS) {
867
+ const re = new RegExp(spec.re.source, 'g');
868
+ let m;
869
+ while ((m = re.exec(body)) !== null) {
870
+ const parenInBody = m.index + m[0].length - 1;
871
+ const args = readBalanced(body, parenInBody, '(', ')');
872
+ if (!args)
873
+ continue;
874
+ // For SQL sinks only the first argument (the query string) is injectable.
875
+ // A tainted value sitting in the bound-params slot — `conn.execute(sql, [id])`,
876
+ // `$queryRawUnsafe(sql, id)` — is parameterized and safe, so don't scan it.
877
+ // maskNonCode keeps `${…}` interpolation, so a real `\`...${id}\`` / `"..."+id`
878
+ // query still shows the ident in arg[0].
879
+ let searchText = args.text;
880
+ if (spec.kind === 'sql') {
881
+ const arg0 = (splitArgs(args.text)[0] ?? '').trim();
882
+ // Raw SQL takes a query string as arg[0]. An object-literal first arg means
883
+ // a structured `.execute({...})` — an HTTP/queue/postback adapter, not SQL.
884
+ if (arg0.startsWith('{'))
885
+ continue;
886
+ searchText = arg0;
887
+ }
888
+ for (let slot = 0; slot < fn.paramSlots.length; slot++) {
889
+ for (const ident of fn.paramSlots[slot]) {
890
+ if (!ident)
891
+ continue;
892
+ if (identAppears(searchText, ident)) {
893
+ // A request param used only as a URL base in a redirect (e.g.
894
+ // `new URL("/login", req.url)`) is not the redirect target.
895
+ if (spec.kind === 'redirect' && appearsOnlyAsUrlBase(searchText, ident))
896
+ continue;
897
+ const key = `${slot}:${spec.kind}`;
898
+ if (seen.has(key))
899
+ continue;
900
+ seen.add(key);
901
+ const sinkOffset = fn.bodyOpenIdx + m.index;
902
+ const sinkLine = lineOf(fileContent, sinkOffset);
903
+ out.push({ slot, paramName: ident, kind: spec.kind, sinkLine, sinkOffset });
904
+ }
905
+ }
906
+ }
907
+ }
908
+ }
909
+ return out;
910
+ }
911
+ // ─────────────────────────────────────────────────────────────────────────
912
+ // Taint at call sites
913
+ // ─────────────────────────────────────────────────────────────────────────
914
+ /** Collect local variables assigned directly from request input within a file. */
915
+ export function taintedLocals(content) {
916
+ const vars = new Set();
917
+ const decl = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*|\{[^}]*\}|\[[^\]]*\])\s*=\s*([^;\n]+)/g;
918
+ let m;
919
+ while ((m = decl.exec(content)) !== null) {
920
+ if (!REQUEST_RE.test(m[2]))
921
+ continue;
922
+ const target = m[1].trim();
923
+ if (target.startsWith('{') || target.startsWith('[')) {
924
+ for (const id of target.match(/[A-Za-z_$][\w$]*/g) ?? [])
925
+ vars.add(id);
926
+ }
927
+ else {
928
+ vars.add(target);
929
+ }
930
+ }
931
+ return vars;
932
+ }
933
+ export function isTainted(argText, locals) {
934
+ if (REQUEST_RE.test(argText))
935
+ return true;
936
+ for (const v of locals) {
937
+ if (identAppears(argText, v))
938
+ return true;
939
+ }
940
+ return false;
941
+ }
942
+ /**
943
+ * Run the full analysis over an in-memory set of source files.
944
+ * Pure and deterministic — the agent is a thin wrapper around this.
945
+ */
946
+ export function analyzeTaint(files) {
947
+ // Pass 1 — discover sink wrappers across all files.
948
+ const wrappers = [];
949
+ const byName = new Map();
950
+ for (const file of files) {
951
+ const masked = maskNonCode(file.content);
952
+ for (const fn of extractFunctions(masked)) {
953
+ if (fn.paramSlots.length === 0)
954
+ continue;
955
+ for (const hit of sinksUsingParams(fn, masked)) {
956
+ const w = {
957
+ fnName: fn.name,
958
+ file: file.path,
959
+ declLine: fn.declLine,
960
+ paramName: hit.paramName,
961
+ paramSlot: hit.slot,
962
+ sinkKind: hit.kind,
963
+ sinkLine: hit.sinkLine,
964
+ };
965
+ wrappers.push(w);
966
+ const list = byName.get(fn.name) ?? [];
967
+ list.push(w);
968
+ byName.set(fn.name, list);
969
+ }
970
+ }
971
+ }
972
+ // Pass 1.5 — GraphQL resolvers whose `args` reaches a sink directly. The
973
+ // resolver itself is the wrapper, but its caller is the GraphQL framework
974
+ // (not visible in code), so we'd never find a tainted call site in pass 2.
975
+ // Emit the flow here instead. Only the args slot (positionally 2nd = idx 1)
976
+ // counts as a request source.
977
+ const flows = [];
978
+ const seen = new Set();
979
+ for (const file of files) {
980
+ const masked = maskNonCode(file.content);
981
+ for (const r of extractResolvers(masked)) {
982
+ for (const hit of sinksUsingParams(r.fn, masked)) {
983
+ if (hit.slot !== 1)
984
+ continue;
985
+ const key = `${file.path}:${hit.sinkLine}:${r.fn.name}:${hit.slot}:${hit.kind}:resolver`;
986
+ if (seen.has(key))
987
+ continue;
988
+ seen.add(key);
989
+ flows.push({
990
+ callFile: file.path,
991
+ callLine: hit.sinkLine,
992
+ wrapperFn: r.fn.name,
993
+ paramSlot: hit.slot,
994
+ sinkFile: file.path,
995
+ sinkKind: hit.kind,
996
+ crossFile: false,
997
+ snippet: snippetOf(file.content, hit.sinkOffset),
998
+ resolverDirect: true,
999
+ });
1000
+ }
1001
+ }
1002
+ }
1003
+ // Pass 2 — find tainted call sites of those wrappers.
1004
+ for (const file of files) {
1005
+ const masked = maskNonCode(file.content);
1006
+ const locals = taintedLocals(masked);
1007
+ // Inside a resolver body, the resolver's args-slot identifiers are also
1008
+ // taint sources. Scoping to the body offset range avoids tainting random
1009
+ // `args` locals elsewhere in the file (the original FP shape).
1010
+ const resolvers = extractResolvers(masked);
1011
+ for (const [name, defs] of byName) {
1012
+ const callRe = new RegExp(`(?<![.\\w])${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\(`, 'g');
1013
+ let m;
1014
+ while ((m = callRe.exec(masked)) !== null) {
1015
+ // Skip the wrapper's own declaration site.
1016
+ const before = masked.slice(Math.max(0, m.index - 12), m.index);
1017
+ if (/\bfunction\s+$/.test(before))
1018
+ continue;
1019
+ const parenIdx = m.index + m[0].length - 1;
1020
+ const args = readBalanced(masked, parenIdx, '(', ')');
1021
+ if (!args)
1022
+ continue;
1023
+ const argList = splitArgs(args.text);
1024
+ let resolverTaint = [];
1025
+ for (const r of resolvers) {
1026
+ if (m.index >= r.bodyStart && m.index < r.bodyEnd) {
1027
+ resolverTaint = unshadowedResolverTaint(r, m.index);
1028
+ break;
1029
+ }
1030
+ }
1031
+ for (const def of defs) {
1032
+ const slotArg = argList[def.paramSlot];
1033
+ if (slotArg === undefined)
1034
+ continue;
1035
+ const tainted = isTainted(slotArg, locals)
1036
+ || (resolverTaint.length > 0 && resolverTaint.some((n) => identAppears(slotArg, n)));
1037
+ if (!tainted)
1038
+ continue;
1039
+ const callLine = lineOf(file.content, m.index);
1040
+ const key = `${file.path}:${callLine}:${name}:${def.paramSlot}:${def.sinkKind}`;
1041
+ if (seen.has(key))
1042
+ continue;
1043
+ seen.add(key);
1044
+ flows.push({
1045
+ callFile: file.path,
1046
+ callLine,
1047
+ wrapperFn: name,
1048
+ paramSlot: def.paramSlot,
1049
+ sinkFile: def.file,
1050
+ sinkKind: def.sinkKind,
1051
+ crossFile: file.path !== def.file,
1052
+ snippet: snippetOf(file.content, m.index),
1053
+ });
1054
+ }
1055
+ }
1056
+ }
1057
+ }
1058
+ // Pass 3 — NestJS: class-method sink-wrappers reached via SAME-CLASS `this.method()`,
1059
+ // plus request params decorated with @Body/@Query/@Param/… as taint sources.
1060
+ // Deliberately isolated from passes 1-2: class methods are never standalone
1061
+ // wrappers (that collided with ORM `.query()` and was reverted), and call sites are
1062
+ // gated to `this.method(...)` within the same class — a bare `.find(`/`.map(` member
1063
+ // call can never match, so Array.prototype methods don't false-positive.
1064
+ for (const file of files) {
1065
+ const masked = maskNonCode(file.content);
1066
+ const locals = taintedLocals(masked);
1067
+ for (const cls of extractClasses(masked)) {
1068
+ // Same-class sink-wrappers (a method whose param reaches a sink), keyed by name.
1069
+ const classWrappers = new Map();
1070
+ for (const method of cls.methods) {
1071
+ const fnDef = {
1072
+ name: method.name, paramSlots: method.paramSlots,
1073
+ bodyText: method.bodyText, bodyOpenIdx: method.bodyAbsIdx,
1074
+ declLine: lineOf(masked, method.bodyAbsIdx),
1075
+ };
1076
+ const hits = sinksUsingParams(fnDef, masked);
1077
+ if (hits.length > 0)
1078
+ classWrappers.set(method.name, hits.map((h) => ({ slot: h.slot, kind: h.kind })));
1079
+ }
1080
+ for (const method of cls.methods) {
1081
+ const sources = method.sourceParamIds;
1082
+ // NestJS flows REQUIRE a decorated request param (@Body/@Query/@Param/…) on
1083
+ // this method — the distinctive, low-false-positive signal (the class-method
1084
+ // analogue of the resolver-signature gate). A plain utility method that merely
1085
+ // uses request-ish NAMES internally — e.g. an HTTP client's
1086
+ // `concurrent(requests)` calling `this.request(req.url, req.body, …)` where
1087
+ // `req` is an outbound config, not inbound input — is correctly excluded.
1088
+ // (Trade-off: Express-in-a-class `handle(req, res)` without decorators is a
1089
+ // conservative MISS rather than an FP; NestJS, the target, always decorates.)
1090
+ if (sources.length === 0)
1091
+ continue;
1092
+ const fnDef = {
1093
+ name: method.name, paramSlots: method.paramSlots,
1094
+ bodyText: method.bodyText, bodyOpenIdx: method.bodyAbsIdx,
1095
+ declLine: lineOf(masked, method.bodyAbsIdx),
1096
+ };
1097
+ // (a) Direct: a decorated request param reaches a sink in this method's own body.
1098
+ for (const hit of sinksUsingParams(fnDef, masked)) {
1099
+ if (!sources.includes(hit.paramName))
1100
+ continue;
1101
+ // A decorated source rebound by a nested callback at the sink is not the request value.
1102
+ if (unshadowedAt(method.bodyText, method.bodyAbsIdx, [hit.paramName], hit.sinkOffset).length === 0)
1103
+ continue;
1104
+ const callLine = lineOf(file.content, hit.sinkOffset);
1105
+ const key = `${file.path}:${callLine}:${method.name}:${hit.slot}:${hit.kind}:nest-direct`;
1106
+ if (seen.has(key))
1107
+ continue;
1108
+ seen.add(key);
1109
+ flows.push({
1110
+ callFile: file.path, callLine, wrapperFn: method.name, paramSlot: hit.slot,
1111
+ sinkFile: file.path, sinkKind: hit.kind, crossFile: false,
1112
+ snippet: snippetOf(file.content, hit.sinkOffset),
1113
+ });
1114
+ }
1115
+ // (b) Laundered: `this.wrapper(tainted)` where wrapper is a same-class sink-wrapper.
1116
+ const callRe = /this\s*\.\s*([A-Za-z_$][\w$]*)\s*\(/g;
1117
+ let cm;
1118
+ while ((cm = callRe.exec(method.bodyText)) !== null) {
1119
+ const targets = classWrappers.get(cm[1]);
1120
+ if (!targets)
1121
+ continue;
1122
+ const parenIdx = cm.index + cm[0].length - 1;
1123
+ const args = readBalanced(method.bodyText, parenIdx, '(', ')');
1124
+ if (!args)
1125
+ continue;
1126
+ const argList = splitArgs(args.text);
1127
+ const callAbs = method.bodyAbsIdx + cm.index;
1128
+ // Drop decorated sources that a nested callback enclosing THIS call rebinds
1129
+ // (e.g. `items.map(body => this.run(body.id))` — the inner `body` is local,
1130
+ // not the request body), mirroring the resolver path's shadow handling.
1131
+ const liveSources = unshadowedAt(method.bodyText, method.bodyAbsIdx, sources, callAbs);
1132
+ for (const t of targets) {
1133
+ const arg = argList[t.slot];
1134
+ if (arg === undefined)
1135
+ continue;
1136
+ const tainted = isTainted(arg, locals) || liveSources.some((s) => identAppears(arg, s));
1137
+ if (!tainted)
1138
+ continue;
1139
+ const callLine = lineOf(file.content, callAbs);
1140
+ const key = `${file.path}:${callLine}:${cm[1]}:${t.slot}:${t.kind}:nest`;
1141
+ if (seen.has(key))
1142
+ continue;
1143
+ seen.add(key);
1144
+ flows.push({
1145
+ callFile: file.path, callLine, wrapperFn: cm[1], paramSlot: t.slot,
1146
+ sinkFile: file.path, sinkKind: t.kind, crossFile: false,
1147
+ snippet: snippetOf(file.content, callAbs),
1148
+ });
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+ }
1154
+ return { wrappers, flows };
1155
+ }
1156
+ // ─────────────────────────────────────────────────────────────────────────
1157
+ // Agent
1158
+ // ─────────────────────────────────────────────────────────────────────────
1159
+ const SINK_LABEL = {
1160
+ sql: 'a raw-SQL',
1161
+ eval: 'a dynamic-code-execution',
1162
+ command: 'a shell-command',
1163
+ 'fs-path': 'a filesystem-path',
1164
+ redirect: 'an HTTP-redirect',
1165
+ ssrf: 'an outbound-HTTP (SSRF)',
1166
+ };
1167
+ export class CrossFileTaintTrackerAgent extends BaseAgent {
1168
+ agentId = 112;
1169
+ agentName = 'Cross-File Taint Tracker';
1170
+ async preFlight() {
1171
+ const root = this.config.projectRoot ?? process.cwd();
1172
+ if (!fs.existsSync(root)) {
1173
+ throw new Error(`projectRoot does not exist: ${root}`);
1174
+ }
1175
+ }
1176
+ async execute() {
1177
+ const findings = [];
1178
+ const projectRoot = this.config.projectRoot ?? process.cwd();
1179
+ const filePaths = new Set();
1180
+ const mapPath = path.join(this.runDir, 'evidence', 'connection-map.json');
1181
+ try {
1182
+ const map = JSON.parse(fs.readFileSync(mapPath, 'utf-8'));
1183
+ for (const f of map.files) {
1184
+ if (!f.isTest)
1185
+ filePaths.add(path.join(projectRoot, f.path));
1186
+ }
1187
+ }
1188
+ catch {
1189
+ for (const f of walk(projectRoot))
1190
+ filePaths.add(f);
1191
+ }
1192
+ const files = [];
1193
+ for (const abs of filePaths) {
1194
+ if (isTestPath(abs, projectRoot))
1195
+ continue;
1196
+ let content;
1197
+ try {
1198
+ content = fs.readFileSync(abs, 'utf-8');
1199
+ }
1200
+ catch {
1201
+ continue;
1202
+ }
1203
+ files.push({ path: relativise(abs, projectRoot), content });
1204
+ }
1205
+ const { wrappers, flows } = analyzeTaint(files);
1206
+ this.persistAudit(projectRoot, files.length, wrappers.length, flows);
1207
+ if (flows.length === 0) {
1208
+ findings.push({
1209
+ id: `${this.agentId}-clean`,
1210
+ type: 'infra-issue',
1211
+ severity: 'info',
1212
+ agentId: this.agentId,
1213
+ module: 'taint-tracker',
1214
+ description: `Scanned ${files.length} non-test file(s), ${wrappers.length} sink-wrapper(s) — no request input reaches a dangerous sink through a helper.`,
1215
+ });
1216
+ return findings;
1217
+ }
1218
+ for (const flow of flows.slice(0, 100)) {
1219
+ const description = flow.resolverDirect
1220
+ ? `GraphQL resolver \`${flow.wrapperFn}\` at ${flow.callFile}:${flow.callLine} reaches ${SINK_LABEL[flow.sinkKind]} sink with its \`args\` directly. The GraphQL framework supplies \`args\` from the client query — validate or parameterise it before the sink. \`${flow.snippet}\``
1221
+ : (() => {
1222
+ const where = flow.crossFile
1223
+ ? `${flow.callFile}:${flow.callLine} passes request data to ${flow.wrapperFn}() (defined in ${flow.sinkFile})`
1224
+ : `${flow.callFile}:${flow.callLine} passes request data to ${flow.wrapperFn}() in the same file`;
1225
+ return `${flow.crossFile ? 'Cross-file' : 'Same-file'} taint flow into ${SINK_LABEL[flow.sinkKind]} sink: ${where}, whose parameter #${flow.paramSlot} reaches the sink unsanitised. Validate or parameterise the input at the boundary before it reaches ${flow.wrapperFn}(). \`${flow.snippet}\``;
1226
+ })();
1227
+ const idSuffix = flow.resolverDirect ? '-resolver' : '';
1228
+ findings.push({
1229
+ id: `${this.agentId}-taint-flow-${flow.callFile.replace(/[^\w]/g, '_')}-${flow.callLine}-${flow.wrapperFn}${idSuffix}`,
1230
+ type: 'code-bug-security',
1231
+ severity: 'high',
1232
+ agentId: this.agentId,
1233
+ module: 'taint-tracker',
1234
+ description,
1235
+ file: flow.callFile,
1236
+ line: flow.callLine,
1237
+ });
1238
+ }
1239
+ findings.push({
1240
+ id: `${this.agentId}-summary`,
1241
+ type: 'infra-issue',
1242
+ severity: 'info',
1243
+ agentId: this.agentId,
1244
+ module: 'taint-tracker',
1245
+ description: `Taint analysis: ${flows.length} flow(s) (${flows.filter(f => f.crossFile).length} cross-file) through ${wrappers.length} sink-wrapper(s) across ${files.length} file(s).`,
1246
+ });
1247
+ return findings;
1248
+ }
1249
+ persistAudit(projectRoot, filesScanned, wrappers, flows) {
1250
+ const audit = {
1251
+ version: 1,
1252
+ generatedAt: new Date().toISOString(),
1253
+ projectRoot,
1254
+ filesScanned,
1255
+ wrappers,
1256
+ flows,
1257
+ };
1258
+ try {
1259
+ const evidenceDir = path.join(this.runDir, 'evidence');
1260
+ fs.mkdirSync(evidenceDir, { recursive: true });
1261
+ fs.writeFileSync(path.join(evidenceDir, 'taint-analysis.json'), JSON.stringify(audit, null, 2), 'utf-8');
1262
+ this.addEvidence({
1263
+ type: 'report',
1264
+ path: 'evidence/taint-analysis.json',
1265
+ description: `Taint analysis: ${flows.length} flow(s) through ${wrappers} sink-wrapper(s) across ${filesScanned} file(s)`,
1266
+ });
1267
+ }
1268
+ catch {
1269
+ // non-fatal
1270
+ }
1271
+ }
1272
+ }
1273
+ //# sourceMappingURL=112-taint-tracker.js.map