brasscoders 2.0.4__py3-none-any.whl

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 (615) hide show
  1. brass/__init__.py +9 -0
  2. brass/cli/__init__.py +7 -0
  3. brass/cli/brass_cli.py +2721 -0
  4. brass/config/patterns.yaml +243 -0
  5. brass/core/__init__.py +13 -0
  6. brass/core/atomic_writer.py +181 -0
  7. brass/core/brassignore.py +182 -0
  8. brass/core/change_detection.py +206 -0
  9. brass/core/error_handling.py +262 -0
  10. brass/core/error_reporter.py +308 -0
  11. brass/core/file_classifier.py +433 -0
  12. brass/core/file_index.py +111 -0
  13. brass/core/file_integrity.py +199 -0
  14. brass/core/finding_cache.py +254 -0
  15. brass/core/framework_registry.py +523 -0
  16. brass/core/logging_config.py +160 -0
  17. brass/core/path_safety.py +36 -0
  18. brass/core/scanner_status.py +56 -0
  19. brass/core/startup_checks.py +247 -0
  20. brass/core/state_validator.py +188 -0
  21. brass/core/user_error_handler.py +202 -0
  22. brass/core/version_check.py +104 -0
  23. brass/data/ast_grep_rules/javascript/sql_injection.yml +27 -0
  24. brass/data/ast_grep_rules/javascript/sql_injection_ts.yml +20 -0
  25. brass/data/ast_grep_rules/javascript/xss.yml +15 -0
  26. brass/data/ast_grep_rules/javascript/xss_ts.yml +14 -0
  27. brass/data/ast_grep_rules/python/command_injection.yml +25 -0
  28. brass/data/ast_grep_rules/python/sql_injection.yml +26 -0
  29. brass/data/ast_grep_rules/python/sql_var_execute.yml +24 -0
  30. brass/data/ast_grep_rules/python/weak_crypto.yml +31 -0
  31. brass/data/ast_grep_rules/sgconfig.yml +3 -0
  32. brass/data/framework_registry/javascript.yaml +205 -0
  33. brass/data/framework_registry/python.yaml +355 -0
  34. brass/data/framework_registry/typescript.yaml +165 -0
  35. brass/data/pysa_models/model_queries.pysa +51 -0
  36. brass/data/pysa_models/stdlib.pysa +82 -0
  37. brass/data/pysa_models/taint.config +62 -0
  38. brass/data/pysa_models/third_party.pysa +78 -0
  39. brass/data/pysa_stubs/django/__init__.pyi +2 -0
  40. brass/data/pysa_stubs/django/db/__init__.pyi +0 -0
  41. brass/data/pysa_stubs/django/db/backends/__init__.pyi +0 -0
  42. brass/data/pysa_stubs/django/db/backends/utils.pyi +4 -0
  43. brass/data/pysa_stubs/django/db/models/__init__.pyi +0 -0
  44. brass/data/pysa_stubs/django/db/models/query.pyi +4 -0
  45. brass/data/pysa_stubs/django/http/__init__.pyi +8 -0
  46. brass/data/pysa_stubs/django/utils/__init__.pyi +0 -0
  47. brass/data/pysa_stubs/django/utils/safestring.pyi +1 -0
  48. brass/data/pysa_stubs/flask/__init__.pyi +26 -0
  49. brass/data/pysa_stubs/httpx/__init__.pyi +4 -0
  50. brass/data/pysa_stubs/requests/__init__.pyi +0 -0
  51. brass/data/pysa_stubs/requests/api.pyi +7 -0
  52. brass/data/pysa_stubs/sqlalchemy/__init__.pyi +3 -0
  53. brass/data/pysa_stubs/sqlalchemy/engine/__init__.pyi +4 -0
  54. brass/data/pysa_stubs/sqlalchemy/orm/__init__.pyi +0 -0
  55. brass/data/pysa_stubs/sqlalchemy/orm/session.pyi +4 -0
  56. brass/data/pysa_stubs/yaml/__init__.pyi +4 -0
  57. brass/data/semgrep_rules/javascript/command_injection.yml +50 -0
  58. brass/data/semgrep_rules/javascript/sql_injection.yml +61 -0
  59. brass/data/semgrep_rules/javascript/ssrf.yml +82 -0
  60. brass/data/semgrep_rules/javascript/xss.yml +44 -0
  61. brass/data/semgrep_rules/python/command_injection.yml +82 -0
  62. brass/data/semgrep_rules/python/deserialization.yml +87 -0
  63. brass/data/semgrep_rules/python/path_traversal.yml +120 -0
  64. brass/data/semgrep_rules/python/sql_injection.yml +77 -0
  65. brass/data/semgrep_rules/python/ssrf.yml +102 -0
  66. brass/data/semgrep_rules/python/xss.yml +86 -0
  67. brass/enrichment/__init__.py +51 -0
  68. brass/enrichment/_token_budget.py +112 -0
  69. brass/enrichment/_wire_clamp.py +42 -0
  70. brass/enrichment/client.py +683 -0
  71. brass/enrichment/filter.py +371 -0
  72. brass/enrichment/project_signature.py +197 -0
  73. brass/filtering/__init__.py +8 -0
  74. brass/filtering/ai_review_filter.py +302 -0
  75. brass/js_analysis/babel_parser.js +416 -0
  76. brass/js_analysis/node_modules/@babel/code-frame/LICENSE +22 -0
  77. brass/js_analysis/node_modules/@babel/code-frame/README.md +19 -0
  78. brass/js_analysis/node_modules/@babel/code-frame/lib/index.js +216 -0
  79. brass/js_analysis/node_modules/@babel/code-frame/lib/index.js.map +1 -0
  80. brass/js_analysis/node_modules/@babel/code-frame/package.json +31 -0
  81. brass/js_analysis/node_modules/@babel/generator/LICENSE +22 -0
  82. brass/js_analysis/node_modules/@babel/generator/README.md +19 -0
  83. brass/js_analysis/node_modules/@babel/generator/lib/buffer.js +317 -0
  84. brass/js_analysis/node_modules/@babel/generator/lib/buffer.js.map +1 -0
  85. brass/js_analysis/node_modules/@babel/generator/lib/generators/base.js +87 -0
  86. brass/js_analysis/node_modules/@babel/generator/lib/generators/base.js.map +1 -0
  87. brass/js_analysis/node_modules/@babel/generator/lib/generators/classes.js +212 -0
  88. brass/js_analysis/node_modules/@babel/generator/lib/generators/classes.js.map +1 -0
  89. brass/js_analysis/node_modules/@babel/generator/lib/generators/deprecated.js +28 -0
  90. brass/js_analysis/node_modules/@babel/generator/lib/generators/deprecated.js.map +1 -0
  91. brass/js_analysis/node_modules/@babel/generator/lib/generators/expressions.js +300 -0
  92. brass/js_analysis/node_modules/@babel/generator/lib/generators/expressions.js.map +1 -0
  93. brass/js_analysis/node_modules/@babel/generator/lib/generators/flow.js +660 -0
  94. brass/js_analysis/node_modules/@babel/generator/lib/generators/flow.js.map +1 -0
  95. brass/js_analysis/node_modules/@babel/generator/lib/generators/index.js +128 -0
  96. brass/js_analysis/node_modules/@babel/generator/lib/generators/index.js.map +1 -0
  97. brass/js_analysis/node_modules/@babel/generator/lib/generators/jsx.js +126 -0
  98. brass/js_analysis/node_modules/@babel/generator/lib/generators/jsx.js.map +1 -0
  99. brass/js_analysis/node_modules/@babel/generator/lib/generators/methods.js +198 -0
  100. brass/js_analysis/node_modules/@babel/generator/lib/generators/methods.js.map +1 -0
  101. brass/js_analysis/node_modules/@babel/generator/lib/generators/modules.js +287 -0
  102. brass/js_analysis/node_modules/@babel/generator/lib/generators/modules.js.map +1 -0
  103. brass/js_analysis/node_modules/@babel/generator/lib/generators/statements.js +279 -0
  104. brass/js_analysis/node_modules/@babel/generator/lib/generators/statements.js.map +1 -0
  105. brass/js_analysis/node_modules/@babel/generator/lib/generators/template-literals.js +40 -0
  106. brass/js_analysis/node_modules/@babel/generator/lib/generators/template-literals.js.map +1 -0
  107. brass/js_analysis/node_modules/@babel/generator/lib/generators/types.js +238 -0
  108. brass/js_analysis/node_modules/@babel/generator/lib/generators/types.js.map +1 -0
  109. brass/js_analysis/node_modules/@babel/generator/lib/generators/typescript.js +724 -0
  110. brass/js_analysis/node_modules/@babel/generator/lib/generators/typescript.js.map +1 -0
  111. brass/js_analysis/node_modules/@babel/generator/lib/index.js +112 -0
  112. brass/js_analysis/node_modules/@babel/generator/lib/index.js.map +1 -0
  113. brass/js_analysis/node_modules/@babel/generator/lib/node/index.js +122 -0
  114. brass/js_analysis/node_modules/@babel/generator/lib/node/index.js.map +1 -0
  115. brass/js_analysis/node_modules/@babel/generator/lib/node/parentheses.js +262 -0
  116. brass/js_analysis/node_modules/@babel/generator/lib/node/parentheses.js.map +1 -0
  117. brass/js_analysis/node_modules/@babel/generator/lib/node/whitespace.js +145 -0
  118. brass/js_analysis/node_modules/@babel/generator/lib/node/whitespace.js.map +1 -0
  119. brass/js_analysis/node_modules/@babel/generator/lib/printer.js +781 -0
  120. brass/js_analysis/node_modules/@babel/generator/lib/printer.js.map +1 -0
  121. brass/js_analysis/node_modules/@babel/generator/lib/source-map.js +85 -0
  122. brass/js_analysis/node_modules/@babel/generator/lib/source-map.js.map +1 -0
  123. brass/js_analysis/node_modules/@babel/generator/lib/token-map.js +191 -0
  124. brass/js_analysis/node_modules/@babel/generator/lib/token-map.js.map +1 -0
  125. brass/js_analysis/node_modules/@babel/generator/package.json +40 -0
  126. brass/js_analysis/node_modules/@babel/helper-globals/LICENSE +22 -0
  127. brass/js_analysis/node_modules/@babel/helper-globals/README.md +19 -0
  128. brass/js_analysis/node_modules/@babel/helper-globals/data/browser-upper.json +911 -0
  129. brass/js_analysis/node_modules/@babel/helper-globals/data/builtin-lower.json +15 -0
  130. brass/js_analysis/node_modules/@babel/helper-globals/data/builtin-upper.json +51 -0
  131. brass/js_analysis/node_modules/@babel/helper-globals/package.json +32 -0
  132. brass/js_analysis/node_modules/@babel/helper-string-parser/LICENSE +22 -0
  133. brass/js_analysis/node_modules/@babel/helper-string-parser/README.md +19 -0
  134. brass/js_analysis/node_modules/@babel/helper-string-parser/lib/index.js +295 -0
  135. brass/js_analysis/node_modules/@babel/helper-string-parser/lib/index.js.map +1 -0
  136. brass/js_analysis/node_modules/@babel/helper-string-parser/package.json +31 -0
  137. brass/js_analysis/node_modules/@babel/helper-validator-identifier/LICENSE +22 -0
  138. brass/js_analysis/node_modules/@babel/helper-validator-identifier/README.md +19 -0
  139. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/identifier.js +70 -0
  140. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/identifier.js.map +1 -0
  141. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/index.js +57 -0
  142. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/index.js.map +1 -0
  143. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/keyword.js +35 -0
  144. brass/js_analysis/node_modules/@babel/helper-validator-identifier/lib/keyword.js.map +1 -0
  145. brass/js_analysis/node_modules/@babel/helper-validator-identifier/package.json +31 -0
  146. brass/js_analysis/node_modules/@babel/parser/CHANGELOG.md +1073 -0
  147. brass/js_analysis/node_modules/@babel/parser/LICENSE +19 -0
  148. brass/js_analysis/node_modules/@babel/parser/README.md +19 -0
  149. brass/js_analysis/node_modules/@babel/parser/bin/babel-parser.js +15 -0
  150. brass/js_analysis/node_modules/@babel/parser/lib/index.js +14586 -0
  151. brass/js_analysis/node_modules/@babel/parser/lib/index.js.map +1 -0
  152. brass/js_analysis/node_modules/@babel/parser/package.json +50 -0
  153. brass/js_analysis/node_modules/@babel/parser/typings/babel-parser.d.ts +239 -0
  154. brass/js_analysis/node_modules/@babel/template/LICENSE +22 -0
  155. brass/js_analysis/node_modules/@babel/template/README.md +19 -0
  156. brass/js_analysis/node_modules/@babel/template/lib/builder.js +69 -0
  157. brass/js_analysis/node_modules/@babel/template/lib/builder.js.map +1 -0
  158. brass/js_analysis/node_modules/@babel/template/lib/formatters.js +61 -0
  159. brass/js_analysis/node_modules/@babel/template/lib/formatters.js.map +1 -0
  160. brass/js_analysis/node_modules/@babel/template/lib/index.js +23 -0
  161. brass/js_analysis/node_modules/@babel/template/lib/index.js.map +1 -0
  162. brass/js_analysis/node_modules/@babel/template/lib/literal.js +69 -0
  163. brass/js_analysis/node_modules/@babel/template/lib/literal.js.map +1 -0
  164. brass/js_analysis/node_modules/@babel/template/lib/options.js +73 -0
  165. brass/js_analysis/node_modules/@babel/template/lib/options.js.map +1 -0
  166. brass/js_analysis/node_modules/@babel/template/lib/parse.js +163 -0
  167. brass/js_analysis/node_modules/@babel/template/lib/parse.js.map +1 -0
  168. brass/js_analysis/node_modules/@babel/template/lib/populate.js +138 -0
  169. brass/js_analysis/node_modules/@babel/template/lib/populate.js.map +1 -0
  170. brass/js_analysis/node_modules/@babel/template/lib/string.js +20 -0
  171. brass/js_analysis/node_modules/@babel/template/lib/string.js.map +1 -0
  172. brass/js_analysis/node_modules/@babel/template/package.json +27 -0
  173. brass/js_analysis/node_modules/@babel/traverse/LICENSE +22 -0
  174. brass/js_analysis/node_modules/@babel/traverse/README.md +19 -0
  175. brass/js_analysis/node_modules/@babel/traverse/lib/cache.js +38 -0
  176. brass/js_analysis/node_modules/@babel/traverse/lib/cache.js.map +1 -0
  177. brass/js_analysis/node_modules/@babel/traverse/lib/context.js +119 -0
  178. brass/js_analysis/node_modules/@babel/traverse/lib/context.js.map +1 -0
  179. brass/js_analysis/node_modules/@babel/traverse/lib/hub.js +19 -0
  180. brass/js_analysis/node_modules/@babel/traverse/lib/hub.js.map +1 -0
  181. brass/js_analysis/node_modules/@babel/traverse/lib/index.js +87 -0
  182. brass/js_analysis/node_modules/@babel/traverse/lib/index.js.map +1 -0
  183. brass/js_analysis/node_modules/@babel/traverse/lib/path/ancestry.js +139 -0
  184. brass/js_analysis/node_modules/@babel/traverse/lib/path/ancestry.js.map +1 -0
  185. brass/js_analysis/node_modules/@babel/traverse/lib/path/comments.js +52 -0
  186. brass/js_analysis/node_modules/@babel/traverse/lib/path/comments.js.map +1 -0
  187. brass/js_analysis/node_modules/@babel/traverse/lib/path/context.js +242 -0
  188. brass/js_analysis/node_modules/@babel/traverse/lib/path/context.js.map +1 -0
  189. brass/js_analysis/node_modules/@babel/traverse/lib/path/conversion.js +612 -0
  190. brass/js_analysis/node_modules/@babel/traverse/lib/path/conversion.js.map +1 -0
  191. brass/js_analysis/node_modules/@babel/traverse/lib/path/evaluation.js +368 -0
  192. brass/js_analysis/node_modules/@babel/traverse/lib/path/evaluation.js.map +1 -0
  193. brass/js_analysis/node_modules/@babel/traverse/lib/path/family.js +346 -0
  194. brass/js_analysis/node_modules/@babel/traverse/lib/path/family.js.map +1 -0
  195. brass/js_analysis/node_modules/@babel/traverse/lib/path/index.js +293 -0
  196. brass/js_analysis/node_modules/@babel/traverse/lib/path/index.js.map +1 -0
  197. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/index.js +149 -0
  198. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/index.js.map +1 -0
  199. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/inferer-reference.js +151 -0
  200. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/inferer-reference.js.map +1 -0
  201. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/inferers.js +207 -0
  202. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/inferers.js.map +1 -0
  203. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/util.js +30 -0
  204. brass/js_analysis/node_modules/@babel/traverse/lib/path/inference/util.js.map +1 -0
  205. brass/js_analysis/node_modules/@babel/traverse/lib/path/introspection.js +398 -0
  206. brass/js_analysis/node_modules/@babel/traverse/lib/path/introspection.js.map +1 -0
  207. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/hoister.js +171 -0
  208. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/hoister.js.map +1 -0
  209. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/removal-hooks.js +37 -0
  210. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/removal-hooks.js.map +1 -0
  211. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/virtual-types-validator.js +163 -0
  212. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/virtual-types-validator.js.map +1 -0
  213. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/virtual-types.js +26 -0
  214. brass/js_analysis/node_modules/@babel/traverse/lib/path/lib/virtual-types.js.map +1 -0
  215. brass/js_analysis/node_modules/@babel/traverse/lib/path/modification.js +230 -0
  216. brass/js_analysis/node_modules/@babel/traverse/lib/path/modification.js.map +1 -0
  217. brass/js_analysis/node_modules/@babel/traverse/lib/path/removal.js +70 -0
  218. brass/js_analysis/node_modules/@babel/traverse/lib/path/removal.js.map +1 -0
  219. brass/js_analysis/node_modules/@babel/traverse/lib/path/replacement.js +263 -0
  220. brass/js_analysis/node_modules/@babel/traverse/lib/path/replacement.js.map +1 -0
  221. brass/js_analysis/node_modules/@babel/traverse/lib/scope/binding.js +84 -0
  222. brass/js_analysis/node_modules/@babel/traverse/lib/scope/binding.js.map +1 -0
  223. brass/js_analysis/node_modules/@babel/traverse/lib/scope/index.js +1039 -0
  224. brass/js_analysis/node_modules/@babel/traverse/lib/scope/index.js.map +1 -0
  225. brass/js_analysis/node_modules/@babel/traverse/lib/scope/lib/renamer.js +131 -0
  226. brass/js_analysis/node_modules/@babel/traverse/lib/scope/lib/renamer.js.map +1 -0
  227. brass/js_analysis/node_modules/@babel/traverse/lib/traverse-node.js +138 -0
  228. brass/js_analysis/node_modules/@babel/traverse/lib/traverse-node.js.map +1 -0
  229. brass/js_analysis/node_modules/@babel/traverse/lib/types.js +3 -0
  230. brass/js_analysis/node_modules/@babel/traverse/lib/types.js.map +1 -0
  231. brass/js_analysis/node_modules/@babel/traverse/lib/visitors.js +258 -0
  232. brass/js_analysis/node_modules/@babel/traverse/lib/visitors.js.map +1 -0
  233. brass/js_analysis/node_modules/@babel/traverse/package.json +35 -0
  234. brass/js_analysis/node_modules/@babel/types/LICENSE +22 -0
  235. brass/js_analysis/node_modules/@babel/types/README.md +19 -0
  236. brass/js_analysis/node_modules/@babel/types/lib/asserts/assertNode.js +16 -0
  237. brass/js_analysis/node_modules/@babel/types/lib/asserts/assertNode.js.map +1 -0
  238. brass/js_analysis/node_modules/@babel/types/lib/asserts/generated/index.js +1251 -0
  239. brass/js_analysis/node_modules/@babel/types/lib/asserts/generated/index.js.map +1 -0
  240. brass/js_analysis/node_modules/@babel/types/lib/ast-types/generated/index.js +3 -0
  241. brass/js_analysis/node_modules/@babel/types/lib/ast-types/generated/index.js.map +1 -0
  242. brass/js_analysis/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js +18 -0
  243. brass/js_analysis/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js.map +1 -0
  244. brass/js_analysis/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js +31 -0
  245. brass/js_analysis/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js.map +1 -0
  246. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/index.js +29 -0
  247. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/index.js.map +1 -0
  248. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/lowercase.js +2896 -0
  249. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/lowercase.js.map +1 -0
  250. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/uppercase.js +274 -0
  251. brass/js_analysis/node_modules/@babel/types/lib/builders/generated/uppercase.js.map +1 -0
  252. brass/js_analysis/node_modules/@babel/types/lib/builders/productions.js +12 -0
  253. brass/js_analysis/node_modules/@babel/types/lib/builders/productions.js.map +1 -0
  254. brass/js_analysis/node_modules/@babel/types/lib/builders/react/buildChildren.js +24 -0
  255. brass/js_analysis/node_modules/@babel/types/lib/builders/react/buildChildren.js.map +1 -0
  256. brass/js_analysis/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js +22 -0
  257. brass/js_analysis/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js.map +1 -0
  258. brass/js_analysis/node_modules/@babel/types/lib/builders/validateNode.js +21 -0
  259. brass/js_analysis/node_modules/@babel/types/lib/builders/validateNode.js.map +1 -0
  260. brass/js_analysis/node_modules/@babel/types/lib/clone/clone.js +12 -0
  261. brass/js_analysis/node_modules/@babel/types/lib/clone/clone.js.map +1 -0
  262. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneDeep.js +12 -0
  263. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneDeep.js.map +1 -0
  264. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js +12 -0
  265. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js.map +1 -0
  266. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneNode.js +107 -0
  267. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneNode.js.map +1 -0
  268. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js +12 -0
  269. brass/js_analysis/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js.map +1 -0
  270. brass/js_analysis/node_modules/@babel/types/lib/comments/addComment.js +15 -0
  271. brass/js_analysis/node_modules/@babel/types/lib/comments/addComment.js.map +1 -0
  272. brass/js_analysis/node_modules/@babel/types/lib/comments/addComments.js +22 -0
  273. brass/js_analysis/node_modules/@babel/types/lib/comments/addComments.js.map +1 -0
  274. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritInnerComments.js +12 -0
  275. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritInnerComments.js.map +1 -0
  276. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritLeadingComments.js +12 -0
  277. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritLeadingComments.js.map +1 -0
  278. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritTrailingComments.js +12 -0
  279. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritTrailingComments.js.map +1 -0
  280. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritsComments.js +17 -0
  281. brass/js_analysis/node_modules/@babel/types/lib/comments/inheritsComments.js.map +1 -0
  282. brass/js_analysis/node_modules/@babel/types/lib/comments/removeComments.js +15 -0
  283. brass/js_analysis/node_modules/@babel/types/lib/comments/removeComments.js.map +1 -0
  284. brass/js_analysis/node_modules/@babel/types/lib/constants/generated/index.js +60 -0
  285. brass/js_analysis/node_modules/@babel/types/lib/constants/generated/index.js.map +1 -0
  286. brass/js_analysis/node_modules/@babel/types/lib/constants/index.js +33 -0
  287. brass/js_analysis/node_modules/@babel/types/lib/constants/index.js.map +1 -0
  288. brass/js_analysis/node_modules/@babel/types/lib/converters/ensureBlock.js +14 -0
  289. brass/js_analysis/node_modules/@babel/types/lib/converters/ensureBlock.js.map +1 -0
  290. brass/js_analysis/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js +66 -0
  291. brass/js_analysis/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js.map +1 -0
  292. brass/js_analysis/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js +14 -0
  293. brass/js_analysis/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js.map +1 -0
  294. brass/js_analysis/node_modules/@babel/types/lib/converters/toBlock.js +29 -0
  295. brass/js_analysis/node_modules/@babel/types/lib/converters/toBlock.js.map +1 -0
  296. brass/js_analysis/node_modules/@babel/types/lib/converters/toComputedKey.js +14 -0
  297. brass/js_analysis/node_modules/@babel/types/lib/converters/toComputedKey.js.map +1 -0
  298. brass/js_analysis/node_modules/@babel/types/lib/converters/toExpression.js +28 -0
  299. brass/js_analysis/node_modules/@babel/types/lib/converters/toExpression.js.map +1 -0
  300. brass/js_analysis/node_modules/@babel/types/lib/converters/toIdentifier.js +25 -0
  301. brass/js_analysis/node_modules/@babel/types/lib/converters/toIdentifier.js.map +1 -0
  302. brass/js_analysis/node_modules/@babel/types/lib/converters/toKeyAlias.js +38 -0
  303. brass/js_analysis/node_modules/@babel/types/lib/converters/toKeyAlias.js.map +1 -0
  304. brass/js_analysis/node_modules/@babel/types/lib/converters/toSequenceExpression.js +20 -0
  305. brass/js_analysis/node_modules/@babel/types/lib/converters/toSequenceExpression.js.map +1 -0
  306. brass/js_analysis/node_modules/@babel/types/lib/converters/toStatement.js +39 -0
  307. brass/js_analysis/node_modules/@babel/types/lib/converters/toStatement.js.map +1 -0
  308. brass/js_analysis/node_modules/@babel/types/lib/converters/valueToNode.js +89 -0
  309. brass/js_analysis/node_modules/@babel/types/lib/converters/valueToNode.js.map +1 -0
  310. brass/js_analysis/node_modules/@babel/types/lib/definitions/core.js +1659 -0
  311. brass/js_analysis/node_modules/@babel/types/lib/definitions/core.js.map +1 -0
  312. brass/js_analysis/node_modules/@babel/types/lib/definitions/deprecated-aliases.js +11 -0
  313. brass/js_analysis/node_modules/@babel/types/lib/definitions/deprecated-aliases.js.map +1 -0
  314. brass/js_analysis/node_modules/@babel/types/lib/definitions/experimental.js +126 -0
  315. brass/js_analysis/node_modules/@babel/types/lib/definitions/experimental.js.map +1 -0
  316. brass/js_analysis/node_modules/@babel/types/lib/definitions/flow.js +495 -0
  317. brass/js_analysis/node_modules/@babel/types/lib/definitions/flow.js.map +1 -0
  318. brass/js_analysis/node_modules/@babel/types/lib/definitions/index.js +100 -0
  319. brass/js_analysis/node_modules/@babel/types/lib/definitions/index.js.map +1 -0
  320. brass/js_analysis/node_modules/@babel/types/lib/definitions/jsx.js +157 -0
  321. brass/js_analysis/node_modules/@babel/types/lib/definitions/jsx.js.map +1 -0
  322. brass/js_analysis/node_modules/@babel/types/lib/definitions/misc.js +33 -0
  323. brass/js_analysis/node_modules/@babel/types/lib/definitions/misc.js.map +1 -0
  324. brass/js_analysis/node_modules/@babel/types/lib/definitions/placeholders.js +27 -0
  325. brass/js_analysis/node_modules/@babel/types/lib/definitions/placeholders.js.map +1 -0
  326. brass/js_analysis/node_modules/@babel/types/lib/definitions/typescript.js +528 -0
  327. brass/js_analysis/node_modules/@babel/types/lib/definitions/typescript.js.map +1 -0
  328. brass/js_analysis/node_modules/@babel/types/lib/definitions/utils.js +292 -0
  329. brass/js_analysis/node_modules/@babel/types/lib/definitions/utils.js.map +1 -0
  330. brass/js_analysis/node_modules/@babel/types/lib/index-legacy.d.ts +2797 -0
  331. brass/js_analysis/node_modules/@babel/types/lib/index.d.ts +3308 -0
  332. brass/js_analysis/node_modules/@babel/types/lib/index.js +584 -0
  333. brass/js_analysis/node_modules/@babel/types/lib/index.js.flow +2650 -0
  334. brass/js_analysis/node_modules/@babel/types/lib/index.js.map +1 -0
  335. brass/js_analysis/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js +15 -0
  336. brass/js_analysis/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js.map +1 -0
  337. brass/js_analysis/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js +65 -0
  338. brass/js_analysis/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js.map +1 -0
  339. brass/js_analysis/node_modules/@babel/types/lib/modifications/inherits.js +28 -0
  340. brass/js_analysis/node_modules/@babel/types/lib/modifications/inherits.js.map +1 -0
  341. brass/js_analysis/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js +17 -0
  342. brass/js_analysis/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js.map +1 -0
  343. brass/js_analysis/node_modules/@babel/types/lib/modifications/removeProperties.js +24 -0
  344. brass/js_analysis/node_modules/@babel/types/lib/modifications/removeProperties.js.map +1 -0
  345. brass/js_analysis/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js +14 -0
  346. brass/js_analysis/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js.map +1 -0
  347. brass/js_analysis/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js +66 -0
  348. brass/js_analysis/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js.map +1 -0
  349. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js +48 -0
  350. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js.map +1 -0
  351. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js +102 -0
  352. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js.map +1 -0
  353. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getFunctionName.js +63 -0
  354. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getFunctionName.js.map +1 -0
  355. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js +13 -0
  356. brass/js_analysis/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js.map +1 -0
  357. brass/js_analysis/node_modules/@babel/types/lib/traverse/traverse.js +50 -0
  358. brass/js_analysis/node_modules/@babel/types/lib/traverse/traverse.js.map +1 -0
  359. brass/js_analysis/node_modules/@babel/types/lib/traverse/traverseFast.js +40 -0
  360. brass/js_analysis/node_modules/@babel/types/lib/traverse/traverseFast.js.map +1 -0
  361. brass/js_analysis/node_modules/@babel/types/lib/utils/deprecationWarning.js +44 -0
  362. brass/js_analysis/node_modules/@babel/types/lib/utils/deprecationWarning.js.map +1 -0
  363. brass/js_analysis/node_modules/@babel/types/lib/utils/inherit.js +13 -0
  364. brass/js_analysis/node_modules/@babel/types/lib/utils/inherit.js.map +1 -0
  365. brass/js_analysis/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js +40 -0
  366. brass/js_analysis/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js.map +1 -0
  367. brass/js_analysis/node_modules/@babel/types/lib/utils/shallowEqual.js +17 -0
  368. brass/js_analysis/node_modules/@babel/types/lib/utils/shallowEqual.js.map +1 -0
  369. brass/js_analysis/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js +13 -0
  370. brass/js_analysis/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js.map +1 -0
  371. brass/js_analysis/node_modules/@babel/types/lib/validators/generated/index.js +2797 -0
  372. brass/js_analysis/node_modules/@babel/types/lib/validators/generated/index.js.map +1 -0
  373. brass/js_analysis/node_modules/@babel/types/lib/validators/is.js +27 -0
  374. brass/js_analysis/node_modules/@babel/types/lib/validators/is.js.map +1 -0
  375. brass/js_analysis/node_modules/@babel/types/lib/validators/isBinding.js +27 -0
  376. brass/js_analysis/node_modules/@babel/types/lib/validators/isBinding.js.map +1 -0
  377. brass/js_analysis/node_modules/@babel/types/lib/validators/isBlockScoped.js +13 -0
  378. brass/js_analysis/node_modules/@babel/types/lib/validators/isBlockScoped.js.map +1 -0
  379. brass/js_analysis/node_modules/@babel/types/lib/validators/isImmutable.js +21 -0
  380. brass/js_analysis/node_modules/@babel/types/lib/validators/isImmutable.js.map +1 -0
  381. brass/js_analysis/node_modules/@babel/types/lib/validators/isLet.js +17 -0
  382. brass/js_analysis/node_modules/@babel/types/lib/validators/isLet.js.map +1 -0
  383. brass/js_analysis/node_modules/@babel/types/lib/validators/isNode.js +12 -0
  384. brass/js_analysis/node_modules/@babel/types/lib/validators/isNode.js.map +1 -0
  385. brass/js_analysis/node_modules/@babel/types/lib/validators/isNodesEquivalent.js +57 -0
  386. brass/js_analysis/node_modules/@babel/types/lib/validators/isNodesEquivalent.js.map +1 -0
  387. brass/js_analysis/node_modules/@babel/types/lib/validators/isPlaceholderType.js +15 -0
  388. brass/js_analysis/node_modules/@babel/types/lib/validators/isPlaceholderType.js.map +1 -0
  389. brass/js_analysis/node_modules/@babel/types/lib/validators/isReferenced.js +96 -0
  390. brass/js_analysis/node_modules/@babel/types/lib/validators/isReferenced.js.map +1 -0
  391. brass/js_analysis/node_modules/@babel/types/lib/validators/isScope.js +18 -0
  392. brass/js_analysis/node_modules/@babel/types/lib/validators/isScope.js.map +1 -0
  393. brass/js_analysis/node_modules/@babel/types/lib/validators/isSpecifierDefault.js +14 -0
  394. brass/js_analysis/node_modules/@babel/types/lib/validators/isSpecifierDefault.js.map +1 -0
  395. brass/js_analysis/node_modules/@babel/types/lib/validators/isType.js +17 -0
  396. brass/js_analysis/node_modules/@babel/types/lib/validators/isType.js.map +1 -0
  397. brass/js_analysis/node_modules/@babel/types/lib/validators/isValidES3Identifier.js +13 -0
  398. brass/js_analysis/node_modules/@babel/types/lib/validators/isValidES3Identifier.js.map +1 -0
  399. brass/js_analysis/node_modules/@babel/types/lib/validators/isValidIdentifier.js +18 -0
  400. brass/js_analysis/node_modules/@babel/types/lib/validators/isValidIdentifier.js.map +1 -0
  401. brass/js_analysis/node_modules/@babel/types/lib/validators/isVar.js +19 -0
  402. brass/js_analysis/node_modules/@babel/types/lib/validators/isVar.js.map +1 -0
  403. brass/js_analysis/node_modules/@babel/types/lib/validators/matchesPattern.js +44 -0
  404. brass/js_analysis/node_modules/@babel/types/lib/validators/matchesPattern.js.map +1 -0
  405. brass/js_analysis/node_modules/@babel/types/lib/validators/react/isCompatTag.js +11 -0
  406. brass/js_analysis/node_modules/@babel/types/lib/validators/react/isCompatTag.js.map +1 -0
  407. brass/js_analysis/node_modules/@babel/types/lib/validators/react/isReactComponent.js +11 -0
  408. brass/js_analysis/node_modules/@babel/types/lib/validators/react/isReactComponent.js.map +1 -0
  409. brass/js_analysis/node_modules/@babel/types/lib/validators/validate.js +42 -0
  410. brass/js_analysis/node_modules/@babel/types/lib/validators/validate.js.map +1 -0
  411. brass/js_analysis/node_modules/@babel/types/package.json +39 -0
  412. brass/js_analysis/node_modules/@jridgewell/gen-mapping/LICENSE +19 -0
  413. brass/js_analysis/node_modules/@jridgewell/gen-mapping/README.md +227 -0
  414. brass/js_analysis/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs +292 -0
  415. brass/js_analysis/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs.map +6 -0
  416. brass/js_analysis/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js +346 -0
  417. brass/js_analysis/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js.map +6 -0
  418. brass/js_analysis/node_modules/@jridgewell/gen-mapping/package.json +71 -0
  419. brass/js_analysis/node_modules/@jridgewell/gen-mapping/src/gen-mapping.ts +614 -0
  420. brass/js_analysis/node_modules/@jridgewell/gen-mapping/src/set-array.ts +82 -0
  421. brass/js_analysis/node_modules/@jridgewell/gen-mapping/src/sourcemap-segment.ts +16 -0
  422. brass/js_analysis/node_modules/@jridgewell/gen-mapping/src/types.ts +61 -0
  423. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts +89 -0
  424. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts.map +1 -0
  425. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts +89 -0
  426. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts.map +1 -0
  427. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts +33 -0
  428. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts.map +1 -0
  429. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts +33 -0
  430. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts.map +1 -0
  431. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts +13 -0
  432. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts.map +1 -0
  433. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts +13 -0
  434. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts.map +1 -0
  435. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/types.d.cts +44 -0
  436. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/types.d.cts.map +1 -0
  437. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/types.d.mts +44 -0
  438. brass/js_analysis/node_modules/@jridgewell/gen-mapping/types/types.d.mts.map +1 -0
  439. brass/js_analysis/node_modules/@jridgewell/resolve-uri/LICENSE +19 -0
  440. brass/js_analysis/node_modules/@jridgewell/resolve-uri/README.md +40 -0
  441. brass/js_analysis/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs +232 -0
  442. brass/js_analysis/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs.map +1 -0
  443. brass/js_analysis/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js +240 -0
  444. brass/js_analysis/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js.map +1 -0
  445. brass/js_analysis/node_modules/@jridgewell/resolve-uri/dist/types/resolve-uri.d.ts +4 -0
  446. brass/js_analysis/node_modules/@jridgewell/resolve-uri/package.json +69 -0
  447. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/LICENSE +19 -0
  448. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/README.md +264 -0
  449. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs +423 -0
  450. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +6 -0
  451. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js +452 -0
  452. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js.map +6 -0
  453. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/package.json +67 -0
  454. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/src/scopes.ts +345 -0
  455. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/src/sourcemap-codec.ts +111 -0
  456. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/src/strings.ts +65 -0
  457. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/src/vlq.ts +55 -0
  458. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts +50 -0
  459. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts.map +1 -0
  460. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts +50 -0
  461. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts.map +1 -0
  462. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts +9 -0
  463. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts.map +1 -0
  464. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts +9 -0
  465. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts.map +1 -0
  466. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts +16 -0
  467. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts.map +1 -0
  468. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts +16 -0
  469. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts.map +1 -0
  470. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts +7 -0
  471. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts.map +1 -0
  472. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts +7 -0
  473. brass/js_analysis/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts.map +1 -0
  474. brass/js_analysis/node_modules/@jridgewell/trace-mapping/LICENSE +19 -0
  475. brass/js_analysis/node_modules/@jridgewell/trace-mapping/README.md +348 -0
  476. brass/js_analysis/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs +504 -0
  477. brass/js_analysis/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs.map +6 -0
  478. brass/js_analysis/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js +558 -0
  479. brass/js_analysis/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js.map +6 -0
  480. brass/js_analysis/node_modules/@jridgewell/trace-mapping/package.json +71 -0
  481. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/binary-search.ts +115 -0
  482. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/by-source.ts +65 -0
  483. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/flatten-map.ts +192 -0
  484. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/resolve.ts +16 -0
  485. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/sort.ts +45 -0
  486. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/sourcemap-segment.ts +23 -0
  487. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/strip-filename.ts +8 -0
  488. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/trace-mapping.ts +504 -0
  489. brass/js_analysis/node_modules/@jridgewell/trace-mapping/src/types.ts +114 -0
  490. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts +33 -0
  491. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts.map +1 -0
  492. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts +33 -0
  493. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts.map +1 -0
  494. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts +8 -0
  495. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts.map +1 -0
  496. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts +8 -0
  497. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts.map +1 -0
  498. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts +9 -0
  499. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts.map +1 -0
  500. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts +9 -0
  501. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts.map +1 -0
  502. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts +4 -0
  503. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts.map +1 -0
  504. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts +4 -0
  505. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts.map +1 -0
  506. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sort.d.cts +3 -0
  507. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sort.d.cts.map +1 -0
  508. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sort.d.mts +3 -0
  509. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sort.d.mts.map +1 -0
  510. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts +17 -0
  511. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts.map +1 -0
  512. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts +17 -0
  513. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts.map +1 -0
  514. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts +5 -0
  515. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts.map +1 -0
  516. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts +5 -0
  517. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts.map +1 -0
  518. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts +80 -0
  519. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts.map +1 -0
  520. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts +80 -0
  521. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts.map +1 -0
  522. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/types.d.cts +107 -0
  523. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/types.d.cts.map +1 -0
  524. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/types.d.mts +107 -0
  525. brass/js_analysis/node_modules/@jridgewell/trace-mapping/types/types.d.mts.map +1 -0
  526. brass/js_analysis/node_modules/debug/LICENSE +20 -0
  527. brass/js_analysis/node_modules/debug/README.md +481 -0
  528. brass/js_analysis/node_modules/debug/package.json +64 -0
  529. brass/js_analysis/node_modules/debug/src/browser.js +272 -0
  530. brass/js_analysis/node_modules/debug/src/common.js +292 -0
  531. brass/js_analysis/node_modules/debug/src/index.js +10 -0
  532. brass/js_analysis/node_modules/debug/src/node.js +263 -0
  533. brass/js_analysis/node_modules/js-tokens/CHANGELOG.md +151 -0
  534. brass/js_analysis/node_modules/js-tokens/LICENSE +21 -0
  535. brass/js_analysis/node_modules/js-tokens/README.md +240 -0
  536. brass/js_analysis/node_modules/js-tokens/index.js +23 -0
  537. brass/js_analysis/node_modules/js-tokens/package.json +30 -0
  538. brass/js_analysis/node_modules/jsesc/LICENSE-MIT.txt +20 -0
  539. brass/js_analysis/node_modules/jsesc/README.md +422 -0
  540. brass/js_analysis/node_modules/jsesc/bin/jsesc +148 -0
  541. brass/js_analysis/node_modules/jsesc/jsesc.js +337 -0
  542. brass/js_analysis/node_modules/jsesc/man/jsesc.1 +94 -0
  543. brass/js_analysis/node_modules/jsesc/package.json +56 -0
  544. brass/js_analysis/node_modules/ms/index.js +162 -0
  545. brass/js_analysis/node_modules/ms/license.md +21 -0
  546. brass/js_analysis/node_modules/ms/package.json +38 -0
  547. brass/js_analysis/node_modules/ms/readme.md +59 -0
  548. brass/js_analysis/node_modules/picocolors/LICENSE +15 -0
  549. brass/js_analysis/node_modules/picocolors/README.md +21 -0
  550. brass/js_analysis/node_modules/picocolors/package.json +25 -0
  551. brass/js_analysis/node_modules/picocolors/picocolors.browser.js +4 -0
  552. brass/js_analysis/node_modules/picocolors/picocolors.d.ts +5 -0
  553. brass/js_analysis/node_modules/picocolors/picocolors.js +75 -0
  554. brass/js_analysis/node_modules/picocolors/types.d.ts +51 -0
  555. brass/js_analysis/package-lock.json +218 -0
  556. brass/js_analysis/package.json +13 -0
  557. brass/licensing/__init__.py +55 -0
  558. brass/licensing/lemonsqueezy.py +205 -0
  559. brass/licensing/store.py +134 -0
  560. brass/models/__init__.py +7 -0
  561. brass/models/finding.py +142 -0
  562. brass/monitoring/__init__.py +7 -0
  563. brass/monitoring/file_watcher.py +408 -0
  564. brass/output/__init__.py +7 -0
  565. brass/output/cross_scanner_overlap.py +132 -0
  566. brass/output/output_generator.py +679 -0
  567. brass/output/redaction_checker.py +254 -0
  568. brass/output/yaml_builders/__init__.py +28 -0
  569. brass/output/yaml_builders/ai_instructions_builder.py +1867 -0
  570. brass/output/yaml_builders/base_builder.py +735 -0
  571. brass/output/yaml_builders/constants.py +44 -0
  572. brass/output/yaml_builders/detailed_analysis_builder.py +111 -0
  573. brass/output/yaml_builders/file_intelligence_builder.py +115 -0
  574. brass/output/yaml_builders/metadata_builder.py +40 -0
  575. brass/output/yaml_builders/privacy_report_builder.py +226 -0
  576. brass/output/yaml_builders/security_report_builder.py +165 -0
  577. brass/output/yaml_builders/statistics_builder.py +264 -0
  578. brass/output/yaml_builders/yaml_utils.py +156 -0
  579. brass/output/yaml_output_generator.py +918 -0
  580. brass/output/yaml_output_generator_v2.py +424 -0
  581. brass/ranking/__init__.py +7 -0
  582. brass/ranking/intelligence_ranker.py +736 -0
  583. brass/scanners/__init__.py +15 -0
  584. brass/scanners/_known_test_values.py +183 -0
  585. brass/scanners/ai_context_coherence_scanner.py +811 -0
  586. brass/scanners/api_security_refactored/__init__.py +35 -0
  587. brass/scanners/api_security_refactored/auth_patterns.py +234 -0
  588. brass/scanners/api_security_refactored/input_validation.py +236 -0
  589. brass/scanners/api_security_refactored/package_hallucination.py +207 -0
  590. brass/scanners/api_security_refactored/scanner.py +213 -0
  591. brass/scanners/api_security_refactored/utils.py +192 -0
  592. brass/scanners/api_security_scanner.py +900 -0
  593. brass/scanners/ast_grep_scanner.py +277 -0
  594. brass/scanners/brass2_privacy_scanner.py +1122 -0
  595. brass/scanners/brass_performance_scanner.py +1615 -0
  596. brass/scanners/content_moderation_scanner.py +793 -0
  597. brass/scanners/file_prefilter_scanner.py +413 -0
  598. brass/scanners/javascript_typescript_scanner.py +771 -0
  599. brass/scanners/noise_reduction_scanner.py +448 -0
  600. brass/scanners/phantom_ai_code_scanner.py +935 -0
  601. brass/scanners/professional_code_scanner.py +1470 -0
  602. brass/scanners/pysa_taint_scanner.py +1501 -0
  603. brass/scanners/secrets_scanner.py +392 -0
  604. brass/scanners/semgrep_taint_scanner.py +478 -0
  605. brass/telemetry/__init__.py +50 -0
  606. brass/telemetry/backend.py +61 -0
  607. brass/telemetry/client.py +82 -0
  608. brass/telemetry/consent.py +82 -0
  609. brasscoders-2.0.4.dist-info/METADATA +251 -0
  610. brasscoders-2.0.4.dist-info/RECORD +615 -0
  611. brasscoders-2.0.4.dist-info/WHEEL +5 -0
  612. brasscoders-2.0.4.dist-info/entry_points.txt +2 -0
  613. brasscoders-2.0.4.dist-info/licenses/LICENSE +202 -0
  614. brasscoders-2.0.4.dist-info/licenses/NOTICE +5 -0
  615. brasscoders-2.0.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,413 @@
1
+ """
2
+ FilePrefilterScanner - Brass2-compliant deterministic file filtering.
3
+
4
+ This scanner implements the first stage of hybrid filtering by excluding files
5
+ that should not be analyzed, following the "traditional tools" philosophy of Brass2.
6
+ """
7
+
8
+ import re
9
+ import os
10
+ from pathlib import Path
11
+ from typing import List, Set, Iterator, Optional
12
+ from datetime import datetime
13
+
14
+ from brass.core.logging_config import get_logger
15
+ from brass.core.error_handling import handle_analysis_error
16
+
17
+ logger = get_logger(__name__)
18
+
19
+ # Configuration constants with environment variable overrides
20
+ MAX_FILE_SIZE_MB = int(os.getenv('BRASS_MAX_FILE_SIZE_MB', '10')) # Maximum file size to analyze (in MB)
21
+ MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024
22
+ MAX_FILES = int(os.getenv('BRASS_MAX_FILES', '100000')) # Maximum files to analyze
23
+ MAX_DEPTH = int(os.getenv('BRASS_MAX_DEPTH', '50')) # Maximum directory depth
24
+ SKIP_BINARY = os.getenv('BRASS_SKIP_BINARY', 'true').lower() == 'true' # Skip binary files
25
+
26
+
27
+ class FilePrefilterScanner:
28
+ """
29
+ Deterministic file prefiltering following Brass2 principles.
30
+
31
+ Implements traditional tools approach - fast, deterministic file exclusions
32
+ to prevent wasteful analysis of irrelevant files.
33
+ """
34
+
35
+ def __init__(self, project_path: str) -> None:
36
+ """
37
+ Initialize FilePrefilterScanner.
38
+
39
+ Args:
40
+ project_path: Root path of project to analyze
41
+
42
+ Raises:
43
+ ValueError: If project_path is empty or None
44
+ FileNotFoundError: If project_path does not exist
45
+ """
46
+ if not project_path:
47
+ raise ValueError("Project path cannot be empty or None")
48
+
49
+ self.project_path = Path(project_path).resolve()
50
+ if not self.project_path.exists():
51
+ raise FileNotFoundError(f"Project path does not exist: {self.project_path}")
52
+
53
+ # Deterministic exclusion patterns (evidence-based)
54
+ self.exclude_patterns = {
55
+ # System files
56
+ '.DS_Store', '.Spotlight-V100', '.Trashes', 'Thumbs.db',
57
+ 'desktop.ini', 'ehthumbs.db',
58
+
59
+ # Version control
60
+ '.git/', '.hg/', '.svn/', '.bzr/',
61
+
62
+ # Build artifacts
63
+ 'build/', 'dist/', 'target/', 'bin/', 'obj/',
64
+ '__pycache__/', '.pytest_cache/', '.coverage/',
65
+ 'node_modules/', '.npm/', 'bower_components/',
66
+ # JS/TS framework build outputs. Aligns this prefilter with
67
+ # FileClassifier.build_patterns (file_classifier.py:214+),
68
+ # which already classifies these as BUILD_OUTPUT. Discovered
69
+ # 2026-05-20: a whisperx scan surfaced 297 SecretsScanner
70
+ # findings inside .next/server/*.js minified bundles —
71
+ # noise that drowns real source-code signal. The bundled-
72
+ # secret risk (NEXT_PUBLIC_* env inlining) is already
73
+ # caught at the source level by the same scanner.
74
+ '.next/', '.nuxt/', '.svelte-kit/', '.turbo/', '.vercel/',
75
+ '.astro/', '.parcel-cache/',
76
+
77
+ # Our own output directory. Scanning .brass/ produces meta-
78
+ # false-positives: SecretsScanner re-matches finding snippets
79
+ # in finding_cache.json, PrivacyScanner re-flags PII patterns
80
+ # quoted in detailed_analysis.yaml, etc. Discovered 2026-05-30
81
+ # during Phase F.6: secrets count climbed scan-over-scan
82
+ # (200 → 289 → 372 → 445) as finding_cache.json grew. The
83
+ # FileClassifier already excludes .brass/ in its build_patterns
84
+ # but the prefilter runs first and has its own pattern list —
85
+ # add it here too to keep the two exclusion lists aligned.
86
+ '.brass/',
87
+
88
+ # Virtual environments and dependencies
89
+ 'venv/', 'env/', '.env/', 'virtualenv/', '.venv/',
90
+ 'site-packages/', 'lib/python', 'lib64/python',
91
+ 'build_env/', 'test_env/', 'dev_env/',
92
+ '.tox/', 'conda-meta/', 'pkgs/',
93
+ '*.egg-info/', '.eggs/', 'pip-wheel-metadata/',
94
+
95
+ # IDE files
96
+ '.vscode/', '.idea/', '*.swp', '*.swo', '*~',
97
+
98
+ # Claude Code agent worktrees — transient, duplicate the
99
+ # project source. Excluding ``.claude/worktrees/`` (and
100
+ # not ``.claude/`` wholesale) preserves any user config
101
+ # in ``.claude/agents/``, ``.claude/skills/``, etc. that
102
+ # the customer might legitimately want scanned. Discovered
103
+ # 2026-05-20: a whisperx scan surfaced 24 redacted-
104
+ # credential findings inside ``.claude/worktrees/agent-*/``
105
+ # — pure noise from a months-old agent run that
106
+ # duplicated the entire repo.
107
+ '.claude/worktrees/',
108
+
109
+ # Binary and compiled files
110
+ '*.pyc', '*.pyo', '*.class', '*.o', '*.so', '*.dll',
111
+ '*.dylib', '*.exe', '*.bin',
112
+
113
+ # Archives (definitely binary, cause hangs)
114
+ '*.zip', '*.tar', '*.tar.gz', '*.tgz', '*.rar',
115
+ '*.7z', '*.gz', '*.bz2', '*.xz',
116
+
117
+ # Database files (binary, can be huge)
118
+ '*.db', '*.sqlite', '*.sqlite3', '*.dump',
119
+
120
+ # Minified files (known to cause parser issues)
121
+ '*.min.js', '*.min.css',
122
+
123
+ # Source maps (generated, very large)
124
+ '*.js.map', '*.css.map', '*.map',
125
+
126
+ # Log files
127
+ '*.log', 'logs/', 'log/',
128
+
129
+ # Temporary files
130
+ 'tmp/', 'temp/', '*.tmp', '*.temp', '*.bak',
131
+ '.cache/', 'cache/',
132
+
133
+ # Test outputs
134
+ 'htmlcov/', '.coverage', 'coverage.xml',
135
+ '.nyc_output/',
136
+
137
+ # Documentation build outputs
138
+ 'docs/build/', '_build/', '_site/',
139
+
140
+ # Media files (definitely binary)
141
+ '*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp',
142
+ '*.ico', '*.mp4', '*.mp3', '*.wav', '*.avi',
143
+
144
+ # Jupyter checkpoints
145
+ '.ipynb_checkpoints/',
146
+
147
+ # macOS specific
148
+ '__MACOSX/', '.AppleDouble/'
149
+ }
150
+
151
+ logger.info(f"FilePrefilterScanner initialized for {self.project_path}")
152
+
153
+ def scan(self) -> List[str]:
154
+ """
155
+ Scan project and return list of files to analyze with production hardening.
156
+
157
+ Returns:
158
+ List of file paths that should be analyzed by other scanners
159
+ """
160
+ try:
161
+ filtered_files = []
162
+ total_discovered = 0
163
+ excluded_count = 0
164
+ binary_excluded = 0
165
+ symlink_loops = 0
166
+
167
+ # Use resource-limited discovery
168
+ for file_path in self._discover_files_safe():
169
+ total_discovered += 1
170
+
171
+ # Apply file limit to total discovered files
172
+ if total_discovered > MAX_FILES:
173
+ logger.warning(f"Reached maximum file limit ({MAX_FILES}), stopping discovery")
174
+ break
175
+
176
+ # Check exclusions with enhanced detection
177
+ exclude_reason = self._should_exclude_enhanced(file_path)
178
+ if exclude_reason:
179
+ excluded_count += 1
180
+ if exclude_reason == 'binary':
181
+ binary_excluded += 1
182
+ elif exclude_reason == 'symlink_loop':
183
+ symlink_loops += 1
184
+ else:
185
+ filtered_files.append(file_path)
186
+
187
+ # Report comprehensive statistics
188
+ exclusion_percentage = (excluded_count / total_discovered) * 100 if total_discovered else 0
189
+ logger.info(f"File prefiltering: {total_discovered} → {len(filtered_files)} files "
190
+ f"({exclusion_percentage:.1f}% excluded)")
191
+
192
+ if binary_excluded > 0:
193
+ logger.info(f" - Excluded {binary_excluded} binary files")
194
+ if symlink_loops > 0:
195
+ logger.warning(f" - Detected {symlink_loops} symlink loops")
196
+
197
+ return filtered_files
198
+
199
+ except Exception as e:
200
+ logger.error(f"File prefiltering failed: {e}")
201
+ handle_analysis_error(str(e), "FilePrefilterScanner", "scan")
202
+ # Return empty list rather than crash - graceful degradation
203
+ return []
204
+
205
+ def _discover_files_safe(self) -> Iterator[str]:
206
+ """
207
+ Discover files with symlink loop protection and depth limits.
208
+
209
+ Yields:
210
+ File paths that exist and are accessible
211
+ """
212
+ visited_real_paths = set()
213
+
214
+ # Use os.walk for better control over traversal
215
+ for root, dirs, files in os.walk(self.project_path, followlinks=True):
216
+ try:
217
+ # Check depth limit
218
+ current_path = Path(root)
219
+ depth = len(current_path.relative_to(self.project_path).parts)
220
+ if depth > MAX_DEPTH:
221
+ logger.debug(f"Skipping deep directory (depth={depth}): {root}")
222
+ dirs[:] = [] # Don't recurse deeper
223
+ continue
224
+
225
+ # Resolve real path to detect symlink loops
226
+ real_root = Path(root).resolve()
227
+ if real_root in visited_real_paths:
228
+ logger.debug(f"Skipping symlink loop: {root} -> {real_root}")
229
+ dirs[:] = [] # Don't recurse into loop
230
+ continue
231
+
232
+ visited_real_paths.add(real_root)
233
+
234
+ # Yield files in this directory
235
+ for filename in files:
236
+ file_path = os.path.join(root, filename)
237
+ yield file_path
238
+
239
+ except (OSError, PermissionError) as e:
240
+ logger.warning(f"Error accessing directory {root}: {e}")
241
+ dirs[:] = [] # Skip this directory tree
242
+
243
+ def _should_exclude(self, file_path: str) -> bool:
244
+ """
245
+ Determine if file should be excluded from analysis.
246
+
247
+ Args:
248
+ file_path: Absolute path to file
249
+
250
+ Returns:
251
+ True if file should be excluded
252
+ """
253
+ try:
254
+ # Validate file path is within project directory (prevent path traversal).
255
+ # Plain ``startswith`` admits sibling dirs whose name shares a prefix —
256
+ # e.g. project ``/tmp/proj`` would accept ``/tmp/proj-attacker/x``. Use
257
+ # the canonical ``is_within`` helper that all rglob walkers now share.
258
+ from brass.core.path_safety import is_within
259
+ file_abs_path = Path(file_path).resolve()
260
+ if not is_within(file_abs_path, self.project_path):
261
+ logger.debug(f"Path traversal attempt blocked: {file_path}")
262
+ return True
263
+
264
+ # Convert to relative path for pattern matching
265
+ relative_path = file_abs_path.relative_to(self.project_path)
266
+ path_str = str(relative_path)
267
+
268
+ # Check against exclusion patterns
269
+ for pattern in self.exclude_patterns:
270
+ if self._matches_pattern(path_str, pattern):
271
+ return True
272
+
273
+ # Size-based exclusion (files > 10MB likely not source code)
274
+ # Use file handle to prevent TOCTOU race condition
275
+ try:
276
+ with open(file_path, 'rb') as f:
277
+ # Seek to end to get file size atomically
278
+ f.seek(0, 2) # SEEK_END
279
+ file_size = f.tell()
280
+ if file_size > MAX_FILE_SIZE_BYTES:
281
+ return True
282
+ # File size is acceptable, reset position for potential future reading
283
+ f.seek(0)
284
+ except (OSError, PermissionError, IOError):
285
+ # If we can't open/read the file, exclude it for safety
286
+ return True
287
+
288
+ return False
289
+
290
+ except Exception as e:
291
+ logger.debug(f"Error checking exclusion for {file_path}: {e}")
292
+ # If we can't determine, exclude for safety
293
+ return True
294
+
295
+ def _matches_pattern(self, path: str, pattern: str) -> bool:
296
+ """
297
+ Check if path matches exclusion pattern.
298
+
299
+ Args:
300
+ path: Relative file path
301
+ pattern: Exclusion pattern
302
+
303
+ Returns:
304
+ True if path matches pattern
305
+ """
306
+ # Directory patterns (end with /) - match directory names in path
307
+ # Example: 'build/' matches 'src/build/output.py'
308
+ # Multi-segment forms like '.claude/worktrees/' match any path
309
+ # whose segments contain that exact subsequence — wrapping
310
+ # both pattern and path with leading/trailing '/' ensures the
311
+ # match is on directory boundaries (so 'claude/wor' won't
312
+ # match 'myclaude/worktree').
313
+ if pattern.endswith('/'):
314
+ directory_name = pattern[:-1] # Remove trailing slash
315
+ if '/' in directory_name:
316
+ return f'/{directory_name}/' in f'/{path}/'
317
+ return directory_name in path.split('/')
318
+
319
+ # Wildcard patterns (contain *) - convert to regex for flexible matching
320
+ # Example: '*.pyc' becomes '.*\.pyc' regex pattern
321
+ if '*' in pattern:
322
+ # Escape special regex characters except *, then convert * to .*
323
+ regex_pattern = re.escape(pattern).replace(r'\*', '.*')
324
+ return re.match(regex_pattern, path) is not None
325
+
326
+ # Exact filename matches (no path separators) - match against filename only
327
+ # Example: 'README' matches 'docs/README' but not 'docs/README.md'
328
+ if '/' not in pattern:
329
+ return pattern == Path(path).name
330
+
331
+ # Path segment matches - simple substring matching for complex patterns
332
+ # Example: 'test/data' matches 'src/test/data/sample.py'
333
+ return pattern in path
334
+
335
+ def _should_exclude_enhanced(self, file_path: str) -> Optional[str]:
336
+ """
337
+ Enhanced exclusion check with reason tracking.
338
+
339
+ Args:
340
+ file_path: Path to check
341
+
342
+ Returns:
343
+ Exclusion reason string or None if not excluded
344
+ """
345
+ # First check standard exclusions
346
+ if self._should_exclude(file_path):
347
+ return 'pattern'
348
+
349
+ # Binary file detection
350
+ if SKIP_BINARY and self._is_binary_file(file_path):
351
+ return 'binary'
352
+
353
+ # Additional symlink validation
354
+ try:
355
+ real_path = Path(file_path).resolve()
356
+ if real_path != Path(file_path):
357
+ # It's a symlink - check if it creates a loop
358
+ if str(real_path).startswith(str(self.project_path)):
359
+ # Check if symlink points to parent directory
360
+ if self.project_path in real_path.parents:
361
+ return 'symlink_loop'
362
+ except (OSError, RuntimeError):
363
+ return 'access_error'
364
+
365
+ return None
366
+
367
+ def _is_binary_file(self, file_path: str) -> bool:
368
+ """
369
+ Detect if file is binary by content inspection.
370
+
371
+ Args:
372
+ file_path: Path to file to check
373
+
374
+ Returns:
375
+ True if file appears to be binary
376
+ """
377
+ try:
378
+ with open(file_path, 'rb') as f:
379
+ # Read first 8KB for analysis
380
+ chunk = f.read(8192)
381
+
382
+ # Empty file is not binary
383
+ if not chunk:
384
+ return False
385
+
386
+ # Check for null bytes (definitive binary indicator)
387
+ if b'\x00' in chunk:
388
+ return True
389
+
390
+ # Check for high ratio of non-text bytes
391
+ text_chars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)))
392
+ non_text_count = sum(1 for byte in chunk if byte not in text_chars)
393
+
394
+ # If more than 30% non-text, likely binary
395
+ if non_text_count / len(chunk) > 0.3:
396
+ return True
397
+
398
+ return False
399
+
400
+ except (OSError, IOError):
401
+ # If can't read, assume binary for safety
402
+ return True
403
+
404
+ def get_exclusion_stats(self) -> dict:
405
+ """Get statistics about file exclusions."""
406
+ return {
407
+ 'exclude_patterns_count': len(self.exclude_patterns),
408
+ 'project_path': str(self.project_path),
409
+ 'last_scan': datetime.now().isoformat(),
410
+ 'max_files': MAX_FILES,
411
+ 'max_depth': MAX_DEPTH,
412
+ 'skip_binary': SKIP_BINARY
413
+ }