patchi 0.7.5__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 (496) hide show
  1. patchi/__init__.py +1 -0
  2. patchi/__main__.py +13 -0
  3. patchi/cli/__init__.py +0 -0
  4. patchi/cli/command_families.py +235 -0
  5. patchi/cli/commands/__init__.py +0 -0
  6. patchi/cli/commands/access_cmd.py +65 -0
  7. patchi/cli/commands/agent_stats_cmd.py +273 -0
  8. patchi/cli/commands/agents_cmd.py +187 -0
  9. patchi/cli/commands/ai_cmd.py +308 -0
  10. patchi/cli/commands/assure_cmd.py +538 -0
  11. patchi/cli/commands/audit_cmd.py +286 -0
  12. patchi/cli/commands/auto_cmd.py +110 -0
  13. patchi/cli/commands/blame_cmd.py +53 -0
  14. patchi/cli/commands/chains_cmd.py +327 -0
  15. patchi/cli/commands/charter_cmd.py +173 -0
  16. patchi/cli/commands/chat_cmd.py +597 -0
  17. patchi/cli/commands/check_cmd.py +232 -0
  18. patchi/cli/commands/cleanup_cmd.py +328 -0
  19. patchi/cli/commands/cockpit_cmd.py +208 -0
  20. patchi/cli/commands/commands_cmd.py +160 -0
  21. patchi/cli/commands/cross_repo_cmd.py +113 -0
  22. patchi/cli/commands/deps_cmd.py +110 -0
  23. patchi/cli/commands/dev_check_cmd.py +342 -0
  24. patchi/cli/commands/dev_cmd.py +445 -0
  25. patchi/cli/commands/doctor_cmd.py +457 -0
  26. patchi/cli/commands/findings_cmd.py +187 -0
  27. patchi/cli/commands/fix_cmd.py +648 -0
  28. patchi/cli/commands/fix_review_cmd.py +273 -0
  29. patchi/cli/commands/heatmap_cmd.py +62 -0
  30. patchi/cli/commands/help_cmd.py +159 -0
  31. patchi/cli/commands/hosted_cmd.py +980 -0
  32. patchi/cli/commands/init.py +456 -0
  33. patchi/cli/commands/key_cmd.py +571 -0
  34. patchi/cli/commands/learn_cmd.py +140 -0
  35. patchi/cli/commands/link_cmd.py +104 -0
  36. patchi/cli/commands/log_cmd.py +57 -0
  37. patchi/cli/commands/memory_cmd.py +215 -0
  38. patchi/cli/commands/model_cmd.py +207 -0
  39. patchi/cli/commands/notify_cmd.py +213 -0
  40. patchi/cli/commands/notify_prompts.py +29 -0
  41. patchi/cli/commands/patch_cmd.py +231 -0
  42. patchi/cli/commands/plan_cmd.py +128 -0
  43. patchi/cli/commands/plugins_cmd.py +307 -0
  44. patchi/cli/commands/queue_cmd.py +152 -0
  45. patchi/cli/commands/quick_cmd.py +159 -0
  46. patchi/cli/commands/ready_cmd.py +292 -0
  47. patchi/cli/commands/report_cmd.py +416 -0
  48. patchi/cli/commands/restrict_cmd.py +127 -0
  49. patchi/cli/commands/review_cmd.py +225 -0
  50. patchi/cli/commands/rules_cmd.py +233 -0
  51. patchi/cli/commands/scan_cmd.py +1908 -0
  52. patchi/cli/commands/settings_cmd.py +45 -0
  53. patchi/cli/commands/status_cmd.py +679 -0
  54. patchi/cli/commands/test_cmd.py +1052 -0
  55. patchi/cli/commands/trend_cmd.py +296 -0
  56. patchi/cli/commands/undo_cmd.py +235 -0
  57. patchi/cli/commands/update_cmd.py +345 -0
  58. patchi/cli/commands/verify_cmd.py +56 -0
  59. patchi/cli/commands/vr_cmd.py +440 -0
  60. patchi/cli/commands/watch_cmd.py +304 -0
  61. patchi/cli/commands/web_cmd.py +114 -0
  62. patchi/cli/console.py +101 -0
  63. patchi/cli/display/__init__.py +1 -0
  64. patchi/cli/display/live_audit.py +269 -0
  65. patchi/cli/display/live_progress.py +169 -0
  66. patchi/cli/framework.py +241 -0
  67. patchi/cli/logo.py +128 -0
  68. patchi/cli/main.py +222 -0
  69. patchi/cli/registry.py +1171 -0
  70. patchi/cli/style.py +68 -0
  71. patchi/cli/themes.py +187 -0
  72. patchi/cli/ux.py +444 -0
  73. patchi/core/__init__.py +0 -0
  74. patchi/core/agents/__init__.py +0 -0
  75. patchi/core/agents/api_fuzzer_agent.py +141 -0
  76. patchi/core/agents/attack_agent.py +242 -0
  77. patchi/core/agents/base.py +1012 -0
  78. patchi/core/agents/bug_predictor_agent.py +58 -0
  79. patchi/core/agents/build_tool_validator.py +150 -0
  80. patchi/core/agents/cache.py +192 -0
  81. patchi/core/agents/chaos_agent.py +133 -0
  82. patchi/core/agents/cicd_generator.py +240 -0
  83. patchi/core/agents/comment_scanner.py +280 -0
  84. patchi/core/agents/console_logging_agent.py +156 -0
  85. patchi/core/agents/coordinator.py +858 -0
  86. patchi/core/agents/core_scanner.py +269 -0
  87. patchi/core/agents/coverage_prioritizer.py +181 -0
  88. patchi/core/agents/dead_code_hygiene.py +296 -0
  89. patchi/core/agents/dead_code_scanner.py +692 -0
  90. patchi/core/agents/dependency_scanner.py +725 -0
  91. patchi/core/agents/doc_claim_agent.py +573 -0
  92. patchi/core/agents/duplicate_scanner.py +568 -0
  93. patchi/core/agents/env_scanner.py +410 -0
  94. patchi/core/agents/feature_flag_agent.py +89 -0
  95. patchi/core/agents/frontend_framework_agent.py +133 -0
  96. patchi/core/agents/goroutine_agent.py +82 -0
  97. patchi/core/agents/governor.py +1972 -0
  98. patchi/core/agents/i18n_agent.py +95 -0
  99. patchi/core/agents/license_compliance.py +247 -0
  100. patchi/core/agents/linking_agent.py +251 -0
  101. patchi/core/agents/memory_profiler_agent.py +102 -0
  102. patchi/core/agents/modernization_agent.py +84 -0
  103. patchi/core/agents/mutation_agent.py +174 -0
  104. patchi/core/agents/nl_query_agent.py +74 -0
  105. patchi/core/agents/promise_rejection_agent.py +100 -0
  106. patchi/core/agents/refactoring_agent.py +286 -0
  107. patchi/core/agents/resource_leak_agent.py +91 -0
  108. patchi/core/agents/route_graph_scanner.py +951 -0
  109. patchi/core/agents/run_agent.py +106 -0
  110. patchi/core/agents/rust_unwrap_agent.py +100 -0
  111. patchi/core/agents/sbom_generator.py +284 -0
  112. patchi/core/agents/scanners.py +67 -0
  113. patchi/core/agents/side/__init__.py +1 -0
  114. patchi/core/agents/side/build_agent.py +65 -0
  115. patchi/core/agents/side/format_agent.py +50 -0
  116. patchi/core/agents/side/install_agent.py +63 -0
  117. patchi/core/agents/side_file_scanner.py +549 -0
  118. patchi/core/agents/snapshot_drift_detector.py +146 -0
  119. patchi/core/agents/spa_route_inventory.py +203 -0
  120. patchi/core/agents/test_scanner.py +442 -0
  121. patchi/core/agents/tool_health.py +109 -0
  122. patchi/core/agents/tool_runner.py +162 -0
  123. patchi/core/agents/type_scanner.py +168 -0
  124. patchi/core/agents/ui_scanner.py +558 -0
  125. patchi/core/ai/__init__.py +20 -0
  126. patchi/core/ai/agent_audit.py +153 -0
  127. patchi/core/ai/agent_profiler.py +277 -0
  128. patchi/core/ai/client.py +499 -0
  129. patchi/core/ai/cost_tracker.py +107 -0
  130. patchi/core/ai/model_router.py +318 -0
  131. patchi/core/ai/orchestrator.py +625 -0
  132. patchi/core/ai/prompts.py +681 -0
  133. patchi/core/ai/smart.py +302 -0
  134. patchi/core/ai/tool_executor.py +24 -0
  135. patchi/core/ai/tools/__init__.py +10 -0
  136. patchi/core/ai/tools/executor.py +621 -0
  137. patchi/core/ai/tools/realize.py +1160 -0
  138. patchi/core/ai/tools/registry.py +1577 -0
  139. patchi/core/assurance/__init__.py +33 -0
  140. patchi/core/assurance/builder.py +211 -0
  141. patchi/core/assurance/graph.py +342 -0
  142. patchi/core/assurance/invariants.py +168 -0
  143. patchi/core/atomic.py +61 -0
  144. patchi/core/attackers/__init__.py +17 -0
  145. patchi/core/attackers/api_abuse.py +89 -0
  146. patchi/core/attackers/auth_bypass.py +73 -0
  147. patchi/core/attackers/base.py +91 -0
  148. patchi/core/attackers/business_logic.py +88 -0
  149. patchi/core/attackers/planner.py +108 -0
  150. patchi/core/attackers/priv_escalation.py +88 -0
  151. patchi/core/attackers/recon.py +87 -0
  152. patchi/core/brain/__init__.py +0 -0
  153. patchi/core/brain/ast_utils/__init__.py +81 -0
  154. patchi/core/brain/ast_utils/assignments.py +219 -0
  155. patchi/core/brain/ast_utils/calls.py +139 -0
  156. patchi/core/brain/ast_utils/config.py +132 -0
  157. patchi/core/brain/ast_utils/control_flow.py +74 -0
  158. patchi/core/brain/ast_utils/dead_symbols.py +205 -0
  159. patchi/core/brain/ast_utils/decorators.py +108 -0
  160. patchi/core/brain/ast_utils/helpers.py +144 -0
  161. patchi/core/brain/ast_utils/imports.py +169 -0
  162. patchi/core/brain/ast_utils/scan.py +143 -0
  163. patchi/core/brain/ast_utils/taint.py +310 -0
  164. patchi/core/brain/audit.py +379 -0
  165. patchi/core/brain/baseline.py +195 -0
  166. patchi/core/brain/blast_radius.py +312 -0
  167. patchi/core/brain/body_tags.py +144 -0
  168. patchi/core/brain/brain.py +1161 -0
  169. patchi/core/brain/brain_context.py +393 -0
  170. patchi/core/brain/brain_watcher.py +340 -0
  171. patchi/core/brain/charter.py +473 -0
  172. patchi/core/brain/classifier.py +214 -0
  173. patchi/core/brain/cockpit.py +350 -0
  174. patchi/core/brain/code_query.py +710 -0
  175. patchi/core/brain/contract.py +889 -0
  176. patchi/core/brain/contract_diff.py +155 -0
  177. patchi/core/brain/council.py +800 -0
  178. patchi/core/brain/cross_repo.py +104 -0
  179. patchi/core/brain/dead_code_tools.py +157 -0
  180. patchi/core/brain/doc_validator.py +197 -0
  181. patchi/core/brain/domain_activator.py +2183 -0
  182. patchi/core/brain/enriched_context.py +220 -0
  183. patchi/core/brain/file_corpus.py +220 -0
  184. patchi/core/brain/framework.py +953 -0
  185. patchi/core/brain/freshness.py +273 -0
  186. patchi/core/brain/git_aware.py +206 -0
  187. patchi/core/brain/heatmap.py +104 -0
  188. patchi/core/brain/ignore_parser.py +153 -0
  189. patchi/core/brain/import_graph.py +486 -0
  190. patchi/core/brain/languages.py +397 -0
  191. patchi/core/brain/layered_brain.py +419 -0
  192. patchi/core/brain/learning.py +229 -0
  193. patchi/core/brain/orphaned_endpoints.py +313 -0
  194. patchi/core/brain/personas/__init__.py +648 -0
  195. patchi/core/brain/personas/bad_user.py +165 -0
  196. patchi/core/brain/personas/base.py +349 -0
  197. patchi/core/brain/proactive.py +807 -0
  198. patchi/core/brain/project_context.py +121 -0
  199. patchi/core/brain/project_reader.py +521 -0
  200. patchi/core/brain/reasoning.py +269 -0
  201. patchi/core/brain/route_detector/__init__.py +15 -0
  202. patchi/core/brain/route_detector/base.py +31 -0
  203. patchi/core/brain/route_detector/csharp.py +209 -0
  204. patchi/core/brain/route_detector/file_based.py +81 -0
  205. patchi/core/brain/route_detector/go.py +152 -0
  206. patchi/core/brain/route_detector/java.py +195 -0
  207. patchi/core/brain/route_detector/javascript.py +197 -0
  208. patchi/core/brain/route_detector/php.py +158 -0
  209. patchi/core/brain/route_detector/python.py +193 -0
  210. patchi/core/brain/route_detector/registry.py +25 -0
  211. patchi/core/brain/route_detector/ruby.py +134 -0
  212. patchi/core/brain/route_detector/rust.py +216 -0
  213. patchi/core/brain/route_detector/swift.py +118 -0
  214. patchi/core/brain/route_mapper.py +265 -0
  215. patchi/core/brain/scanner.py +2136 -0
  216. patchi/core/brain/secrets.py +280 -0
  217. patchi/core/brain/symbol_graph.py +1955 -0
  218. patchi/core/brain/team.py +28 -0
  219. patchi/core/brain/trace_log.py +132 -0
  220. patchi/core/brain/type_checker/__init__.py +65 -0
  221. patchi/core/brain/type_checker/base.py +60 -0
  222. patchi/core/brain/type_checker/csharp.py +59 -0
  223. patchi/core/brain/type_checker/dart.py +59 -0
  224. patchi/core/brain/type_checker/go.py +81 -0
  225. patchi/core/brain/type_checker/java.py +75 -0
  226. patchi/core/brain/type_checker/kotlin.py +75 -0
  227. patchi/core/brain/type_checker/php.py +88 -0
  228. patchi/core/brain/type_checker/python.py +87 -0
  229. patchi/core/brain/type_checker/rust.py +81 -0
  230. patchi/core/brain/type_checker/swift.py +59 -0
  231. patchi/core/brain/type_checker/typescript.py +298 -0
  232. patchi/core/brain/understander.py +130 -0
  233. patchi/core/brain/verify.py +379 -0
  234. patchi/core/campaigns/__init__.py +14 -0
  235. patchi/core/campaigns/base.py +62 -0
  236. patchi/core/campaigns/data_flow_abuse.py +153 -0
  237. patchi/core/campaigns/orchestrator.py +140 -0
  238. patchi/core/campaigns/state_transitions.py +178 -0
  239. patchi/core/ci_bundle.py +104 -0
  240. patchi/core/config.py +311 -0
  241. patchi/core/constants.py +245 -0
  242. patchi/core/debug/__init__.py +25 -0
  243. patchi/core/debug/adapters/__init__.py +11 -0
  244. patchi/core/debug/adapters/codelldb.py +379 -0
  245. patchi/core/debug/adapters/node.py +222 -0
  246. patchi/core/debug/adapters/powershell.py +210 -0
  247. patchi/core/debug/adapters/python.py +244 -0
  248. patchi/core/debug/capture.py +210 -0
  249. patchi/core/debug/dap_client.py +268 -0
  250. patchi/core/detector/__init__.py +0 -0
  251. patchi/core/detector/audit.py +194 -0
  252. patchi/core/detector/bus.py +226 -0
  253. patchi/core/detector/dispatcher.py +275 -0
  254. patchi/core/detector/event.py +254 -0
  255. patchi/core/detector/sigma_engine.py +378 -0
  256. patchi/core/detector/triage.py +289 -0
  257. patchi/core/export/sarif.py +113 -0
  258. patchi/core/fix/__init__.py +17 -0
  259. patchi/core/fix/applier.py +574 -0
  260. patchi/core/fix/base.py +510 -0
  261. patchi/core/fix/code_fixer.py +169 -0
  262. patchi/core/fix/dead_code_remover.py +131 -0
  263. patchi/core/fix/fix_agents.py +775 -0
  264. patchi/core/fix/patch.py +444 -0
  265. patchi/core/fix/risk_gate.py +383 -0
  266. patchi/core/fix/security_fixer.py +93 -0
  267. patchi/core/fix/verify_loop.py +204 -0
  268. patchi/core/fuzz/__init__.py +8 -0
  269. patchi/core/fuzz/corpus.py +137 -0
  270. patchi/core/fuzz/input_fuzzer.py +256 -0
  271. patchi/core/fuzz/sequence_fuzzer.py +162 -0
  272. patchi/core/fuzz/state_fuzzer.py +236 -0
  273. patchi/core/health.py +407 -0
  274. patchi/core/hosted/__init__.py +1 -0
  275. patchi/core/hosted/anomaly.py +298 -0
  276. patchi/core/hosted/audit_log.py +102 -0
  277. patchi/core/hosted/compliance_report.py +148 -0
  278. patchi/core/hosted/ip_reputation.py +169 -0
  279. patchi/core/hosted/log_parsers.py +251 -0
  280. patchi/core/hosted/tokens.py +127 -0
  281. patchi/core/hosted/watchlist.py +164 -0
  282. patchi/core/hosted/webhooks.py +156 -0
  283. patchi/core/memory.py +437 -0
  284. patchi/core/notifications/__init__.py +18 -0
  285. patchi/core/notifications/channels.py +192 -0
  286. patchi/core/notifications/digest.py +141 -0
  287. patchi/core/notifications/escalation.py +158 -0
  288. patchi/core/notifications/notifier.py +182 -0
  289. patchi/core/notifications/quiet_hours.py +69 -0
  290. patchi/core/plugins/__init__.py +48 -0
  291. patchi/core/plugins/analyzer.py +326 -0
  292. patchi/core/plugins/analyzers/__init__.py +6 -0
  293. patchi/core/plugins/analyzers/dead_code_analyzer.py +120 -0
  294. patchi/core/plugins/analyzers/secret_scanner.py +158 -0
  295. patchi/core/plugins/analyzers/todo_scanner.py +115 -0
  296. patchi/core/plugins/registry.py +335 -0
  297. patchi/core/queue.py +375 -0
  298. patchi/core/reliability/__init__.py +13 -0
  299. patchi/core/reliability/chaos.py +163 -0
  300. patchi/core/reliability/fault_injector.py +172 -0
  301. patchi/core/reliability/idempotency.py +128 -0
  302. patchi/core/reliability/recovery.py +147 -0
  303. patchi/core/runtime/__init__.py +5 -0
  304. patchi/core/runtime/tracer.py +230 -0
  305. patchi/core/scan_bus.py +156 -0
  306. patchi/core/security/__init__.py +1 -0
  307. patchi/core/security/ai_validator.py +462 -0
  308. patchi/core/security/app_mapper.py +216 -0
  309. patchi/core/security/app_profile.py +464 -0
  310. patchi/core/security/attack_feedback.py +141 -0
  311. patchi/core/security/attack_scenarios/__init__.py +1 -0
  312. patchi/core/security/attack_tree.py +176 -0
  313. patchi/core/security/auth_audit_agent.py +344 -0
  314. patchi/core/security/authz_agent.py +602 -0
  315. patchi/core/security/auto_fix_proactive.py +620 -0
  316. patchi/core/security/auto_fixer.py +660 -0
  317. patchi/core/security/auto_ticket.py +53 -0
  318. patchi/core/security/bandit_agent.py +152 -0
  319. patchi/core/security/blast_radius.py +226 -0
  320. patchi/core/security/browser_tester.py +333 -0
  321. patchi/core/security/business_logic_agent.py +263 -0
  322. patchi/core/security/catch_block_auditor.py +395 -0
  323. patchi/core/security/cdn_cache_agent.py +357 -0
  324. patchi/core/security/chain_analyzer.py +321 -0
  325. patchi/core/security/chain_to_assurance.py +168 -0
  326. patchi/core/security/charter.py +510 -0
  327. patchi/core/security/cloud_waf_detector.py +295 -0
  328. patchi/core/security/codeql_agent.py +233 -0
  329. patchi/core/security/compliance_agent.py +348 -0
  330. patchi/core/security/confidence_gate.py +423 -0
  331. patchi/core/security/container_scanner.py +282 -0
  332. patchi/core/security/crypto_agent.py +378 -0
  333. patchi/core/security/cve_monitor.py +262 -0
  334. patchi/core/security/dast_agent.py +865 -0
  335. patchi/core/security/defectdojo.py +238 -0
  336. patchi/core/security/defenders/__init__.py +75 -0
  337. patchi/core/security/defenders/auth_middleware.py +115 -0
  338. patchi/core/security/defenders/base.py +97 -0
  339. patchi/core/security/defenders/block_ip.py +71 -0
  340. patchi/core/security/defenders/block_ws_origin.py +36 -0
  341. patchi/core/security/defenders/crypto_fix.py +118 -0
  342. patchi/core/security/defenders/enforce_rate_limit.py +108 -0
  343. patchi/core/security/defenders/fix_code.py +93 -0
  344. patchi/core/security/defenders/invalidate_session.py +40 -0
  345. patchi/core/security/defenders/patch_config.py +70 -0
  346. patchi/core/security/defenders/rotate_secret.py +54 -0
  347. patchi/core/security/defenders/suspend_account.py +41 -0
  348. patchi/core/security/defenders/update_dependency.py +160 -0
  349. patchi/core/security/defense_layer.py +217 -0
  350. patchi/core/security/dependency_vulnerability_agent.py +616 -0
  351. patchi/core/security/detection_pipeline.py +289 -0
  352. patchi/core/security/dns_security_agent.py +497 -0
  353. patchi/core/security/domain_activator_v2.py +913 -0
  354. patchi/core/security/domain_loader.py +1004 -0
  355. patchi/core/security/domains/__init__.py +0 -0
  356. patchi/core/security/email_authentication_agent.py +417 -0
  357. patchi/core/security/env_var_validator.py +304 -0
  358. patchi/core/security/evidence.py +100 -0
  359. patchi/core/security/falco_runtime_agent.py +387 -0
  360. patchi/core/security/fix-playbooks/__init__.py +0 -0
  361. patchi/core/security/gated_finding.py +85 -0
  362. patchi/core/security/git_diff_activator.py +367 -0
  363. patchi/core/security/governance.py +208 -0
  364. patchi/core/security/gradual_gate.py +34 -0
  365. patchi/core/security/history.py +315 -0
  366. patchi/core/security/iac_scanner.py +250 -0
  367. patchi/core/security/ignore_expiry.py +111 -0
  368. patchi/core/security/ignore_learner.py +416 -0
  369. patchi/core/security/injection_agent.py +319 -0
  370. patchi/core/security/insecure_randomness_agent.py +288 -0
  371. patchi/core/security/intent_analyzer.py +326 -0
  372. patchi/core/security/jwt_agent.py +453 -0
  373. patchi/core/security/kubernetes_agent.py +638 -0
  374. patchi/core/security/layer2_orchestrator.py +341 -0
  375. patchi/core/security/llm_security_agent.py +252 -0
  376. patchi/core/security/misconfig_agent.py +600 -0
  377. patchi/core/security/mobile_security_agent.py +474 -0
  378. patchi/core/security/network_agent.py +376 -0
  379. patchi/core/security/noise_filter.py +274 -0
  380. patchi/core/security/orchestrator.py +313 -0
  381. patchi/core/security/pattern_context.py +125 -0
  382. patchi/core/security/pattern_loader.py +101 -0
  383. patchi/core/security/pentest/__init__.py +4 -0
  384. patchi/core/security/pentest/base.py +58 -0
  385. patchi/core/security/pentest/dalfox_adapter.py +40 -0
  386. patchi/core/security/pentest/ffuf_adapter.py +48 -0
  387. patchi/core/security/pentest/nuclei_adapter.py +50 -0
  388. patchi/core/security/pentest/registry.py +80 -0
  389. patchi/core/security/pentest/shannon_adapter.py +107 -0
  390. patchi/core/security/pentest/sqlmap_adapter.py +56 -0
  391. patchi/core/security/pentest/zap_adapter.py +52 -0
  392. patchi/core/security/plan_auditor.py +276 -0
  393. patchi/core/security/policy_engine.py +272 -0
  394. patchi/core/security/prechecks.py +172 -0
  395. patchi/core/security/precommit_hook.py +247 -0
  396. patchi/core/security/privacy_agent.py +361 -0
  397. patchi/core/security/push_notification_agent.py +417 -0
  398. patchi/core/security/pysa_agent.py +143 -0
  399. patchi/core/security/reasoning.py +442 -0
  400. patchi/core/security/red_team_agent.py +184 -0
  401. patchi/core/security/red_team_engine.py +1142 -0
  402. patchi/core/security/remediation.py +360 -0
  403. patchi/core/security/request_interceptor.py +294 -0
  404. patchi/core/security/runtime_validator.py +245 -0
  405. patchi/core/security/saml_sso_agent.py +401 -0
  406. patchi/core/security/sast_agent.py +213 -0
  407. patchi/core/security/sast_gate.py +95 -0
  408. patchi/core/security/scheduler.py +287 -0
  409. patchi/core/security/secrets_runtime_agent.py +476 -0
  410. patchi/core/security/security_agents.py +175 -0
  411. patchi/core/security/security_config.py +551 -0
  412. patchi/core/security/security_probe.py +762 -0
  413. patchi/core/security/security_taint.py +1005 -0
  414. patchi/core/security/sensitive_data_agent.py +271 -0
  415. patchi/core/security/service_mesh_agent.py +412 -0
  416. patchi/core/security/session_management_agent.py +245 -0
  417. patchi/core/security/ssrf_agent.py +422 -0
  418. patchi/core/security/supply_chain.py +449 -0
  419. patchi/core/security/threat_model_generator.py +378 -0
  420. patchi/core/security/threat_model_updater.py +196 -0
  421. patchi/core/security/tool_adapters.py +135 -0
  422. patchi/core/security/tool_verify.py +173 -0
  423. patchi/core/security/websocket_security_agent.py +188 -0
  424. patchi/core/snapshot.py +242 -0
  425. patchi/core/tenant.py +386 -0
  426. patchi/core/testing/__init__.py +17 -0
  427. patchi/core/testing/_browser.py +147 -0
  428. patchi/core/testing/ads_agent.py +141 -0
  429. patchi/core/testing/api_contract_agent.py +450 -0
  430. patchi/core/testing/app_discovery_agent.py +641 -0
  431. patchi/core/testing/app_launcher.py +184 -0
  432. patchi/core/testing/browser_test_agent.py +516 -0
  433. patchi/core/testing/e2e_flow_agent.py +354 -0
  434. patchi/core/testing/flake_detector_agent.py +292 -0
  435. patchi/core/testing/gate.py +31 -0
  436. patchi/core/testing/live_test_runner.py +304 -0
  437. patchi/core/testing/live_v2/__init__.py +1 -0
  438. patchi/core/testing/live_v2/browser_pool.py +349 -0
  439. patchi/core/testing/live_v2/browser_test_runner.py +313 -0
  440. patchi/core/testing/live_v2/runner.py +626 -0
  441. patchi/core/testing/live_v2/screenshot_manager.py +474 -0
  442. patchi/core/testing/live_v2/stress_orchestrator.py +523 -0
  443. patchi/core/testing/live_v2/video_recorder.py +303 -0
  444. patchi/core/testing/regression_agent.py +302 -0
  445. patchi/core/testing/security_test_agent.py +253 -0
  446. patchi/core/testing/stress_test_agent.py +203 -0
  447. patchi/core/testing/test_agents.py +50 -0
  448. patchi/core/testing/test_config.py +194 -0
  449. patchi/core/testing/ui_accessibility_agent.py +324 -0
  450. patchi/core/testing/ui_button_agent.py +294 -0
  451. patchi/core/testing/ui_layout_agent.py +330 -0
  452. patchi/core/testing/unit_test_agent.py +1149 -0
  453. patchi/core/testing/visual_regression_agent.py +260 -0
  454. patchi/web/__init__.py +1 -0
  455. patchi/web/api/__init__.py +1 -0
  456. patchi/web/api/brain_map.py +114 -0
  457. patchi/web/api/charts.py +47 -0
  458. patchi/web/api/chat.py +224 -0
  459. patchi/web/api/cicd.py +576 -0
  460. patchi/web/api/dast_evidence.py +49 -0
  461. patchi/web/api/dev_check.py +320 -0
  462. patchi/web/api/fix.py +134 -0
  463. patchi/web/api/guard.py +65 -0
  464. patchi/web/api/hosted.py +128 -0
  465. patchi/web/api/hosted_v2.py +234 -0
  466. patchi/web/api/live_testing.py +699 -0
  467. patchi/web/api/scan.py +582 -0
  468. patchi/web/api/smart.py +111 -0
  469. patchi/web/api/tenant.py +117 -0
  470. patchi/web/api/tools.py +85 -0
  471. patchi/web/api_legacy.py +2401 -0
  472. patchi/web/app.py +310 -0
  473. patchi/web/events.py +483 -0
  474. patchi/web/routes/__init__.py +1 -0
  475. patchi/web/routes/assurance.py +541 -0
  476. patchi/web/routes/brain.py +36 -0
  477. patchi/web/routes/charter.py +227 -0
  478. patchi/web/routes/chat.py +23 -0
  479. patchi/web/routes/dashboard.py +558 -0
  480. patchi/web/routes/dashboard_v2.py +402 -0
  481. patchi/web/routes/findings.py +330 -0
  482. patchi/web/routes/guard.py +35 -0
  483. patchi/web/routes/history.py +126 -0
  484. patchi/web/routes/landing.py +52 -0
  485. patchi/web/routes/live_testing.py +24 -0
  486. patchi/web/routes/review.py +57 -0
  487. patchi/web/routes/self_improvement.py +110 -0
  488. patchi/web/routes/settings.py +49 -0
  489. patchi/web/routes/tokens.py +29 -0
  490. patchi/web/spawn.py +139 -0
  491. patchi/web/ws.py +141 -0
  492. patchi-0.7.5.dist-info/METADATA +315 -0
  493. patchi-0.7.5.dist-info/RECORD +496 -0
  494. patchi-0.7.5.dist-info/WHEEL +5 -0
  495. patchi-0.7.5.dist-info/licenses/LICENSE +60 -0
  496. patchi-0.7.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,53 @@
1
+ """
2
+ AutoTicket §10.2.4 — File Jira/GitHub Issues for detected bugs with assignee via CODEOWNERS/blame.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ from pathlib import Path
9
+
10
+ _log = logging.getLogger("patchi.security.auto_ticket")
11
+
12
+ def _match_owner(owners: dict, file: str) -> str:
13
+ """CODEOWNERS glob match (longest pattern wins), not exact lookup."""
14
+ import fnmatch
15
+
16
+ best, best_len = "", -1
17
+ for pattern, owner in owners.items():
18
+ if fnmatch.fnmatch(file, pattern) and len(pattern) > best_len:
19
+ best, best_len = owner, len(pattern)
20
+ return best
21
+
22
+ def create_tickets(root: Path, findings: list[dict], dry_run: bool = True) -> list[dict]:
23
+ tickets=[]
24
+ # parse CODEOWNERS for assignee
25
+ owners={}
26
+ co=root/".github/CODEOWNERS"
27
+ if co.exists():
28
+ for line in co.read_text(encoding="utf-8", errors="replace").splitlines():
29
+ if line.strip() and not line.startswith("#"):
30
+ parts=line.split()
31
+ if len(parts)>=2:
32
+ owners[parts[0]]=parts[-1].lstrip("@")
33
+ for f in findings[:10]:
34
+ assignee = _match_owner(owners, f.get("file", "")) or owners.get("*", "")
35
+ # blame fallback
36
+ if not assignee:
37
+ try:
38
+ from patchi.core.brain.git_aware import blame_line
39
+ info=blame_line(f.get("file",""), f.get("line",1), root)
40
+ if info:
41
+ assignee=info.get("author","")
42
+ except Exception as exc: # noqa: BLE001
43
+ _log.debug("blame for ticket failed: %s", exc)
44
+ ticket={
45
+ "title": f.get("message","")[:80] or f.get("type",""),
46
+ "file": f.get("file",""), "line": f.get("line",0),
47
+ "assignee": assignee, "dry_run": dry_run,
48
+ }
49
+ tickets.append(ticket)
50
+ if not dry_run:
51
+ # Real API calls would go here: GitHub Issues API / Jira REST
52
+ pass
53
+ return tickets
@@ -0,0 +1,152 @@
1
+ """
2
+ BanditAgent - Bandit security linter integration.
3
+
4
+ Bandit is a Python security linter that finds common security issues.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import logging
10
+ import subprocess
11
+ import tempfile
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ from patchi.core.agents.base import (
16
+ AgentDomain,
17
+ AgentGroup,
18
+ AgentInput,
19
+ AgentResult,
20
+ AgentStatus,
21
+ BaseAgent,
22
+ register,
23
+ )
24
+
25
+ _log = logging.getLogger("patchi.security.agents.bandit_agent")
26
+
27
+
28
+ @register
29
+ class BanditAgent(BaseAgent):
30
+ """
31
+ BanditAgent - Bandit security linter integration.
32
+
33
+ Bandit is a Python security linter that finds common security issues
34
+ like SQL injection, XSS, hardcoded passwords, etc.
35
+ """
36
+
37
+ group = AgentGroup.SECURITY
38
+ domain = AgentDomain.CODE_QUALITY
39
+ name = "BanditAgent"
40
+ description = "Bandit security linter for Python"
41
+ timeout = 120
42
+
43
+ def _run(self, inp: AgentInput, result: AgentResult) -> None:
44
+ """Run Bandit analysis on the project."""
45
+ if not self._is_bandit_available():
46
+ result.status = AgentStatus.SKIPPED
47
+ result.data["error"] = "Bandit not installed"
48
+ return
49
+
50
+ findings = self._run_bandit(inp.root)
51
+
52
+ for finding_data in findings:
53
+ finding = self._create_finding(finding_data)
54
+ result.add_finding(finding)
55
+
56
+ result.status = AgentStatus.DONE
57
+ result.files_scanned = 1
58
+
59
+ def _is_bandit_available(self) -> bool:
60
+ """Check if Bandit is installed and available."""
61
+ try:
62
+ result = subprocess.run(["bandit", "--version"], capture_output=True, timeout=10)
63
+ return result.returncode == 0
64
+ except FileNotFoundError:
65
+ return False
66
+
67
+ def _run_bandit(self, root: Path) -> list[dict[str, Any]]:
68
+ """Run Bandit and parse JSON output."""
69
+ findings = []
70
+
71
+ with tempfile.TemporaryDirectory() as tmpdir:
72
+ output_file = Path(tmpdir) / "bandit_output.json"
73
+
74
+ try:
75
+ subprocess.run(
76
+ ["bandit", "-r", "--format", "json", "--output", str(output_file), str(root)],
77
+ capture_output=True,
78
+ timeout=120,
79
+ cwd=root,
80
+ )
81
+
82
+ if output_file.exists():
83
+ with open(output_file) as f:
84
+ data = json.load(f)
85
+ return self._parse_bandit_output(data)
86
+
87
+ except subprocess.TimeoutExpired:
88
+ _log.warning("Bandit timed out")
89
+ except Exception as e:
90
+ _log.warning(f"Bandit execution failed: {e}")
91
+
92
+ return findings
93
+
94
+ def _parse_bandit_output(self, data: dict[str, Any]) -> list[dict[str, Any]]:
95
+ """Parse Bandit JSON output into findings (full fidelity)."""
96
+ findings = []
97
+
98
+ for result in data.get("results", []):
99
+ findings.append(
100
+ {
101
+ "type": result.get("test_id", "bandit_finding"),
102
+ "severity": result.get("severity", "MEDIUM"),
103
+ "file": result.get("filename", ""),
104
+ "line": result.get("line_number", 0),
105
+ "message": result.get("issue_text", ""),
106
+ # Bandit embeds CWE as {"id": "CWE-78"} (newer) or plain text
107
+ "cwe": self._extract_cwe(result),
108
+ "confidence": self._map_confidence(result.get("confidence", "MEDIUM")),
109
+ "snippet": (result.get("code") or "").strip(),
110
+ "more_info": result.get("more_info", ""),
111
+ }
112
+ )
113
+ return findings
114
+
115
+ def _extract_cwe(self, result: dict[str, Any]) -> str:
116
+ cwe = result.get("issue_cwe") or result.get("cwe")
117
+ if isinstance(cwe, dict):
118
+ return str(cwe.get("id", "") or "")
119
+ if cwe:
120
+ return str(cwe)
121
+ # Older bandit: derive from test_id via issue metadata link
122
+ return ""
123
+
124
+ def _map_confidence(self, confidence: str) -> float:
125
+ """Map Bandit confidence to float."""
126
+ mapping = {
127
+ "HIGH": 0.9,
128
+ "MEDIUM": 0.6,
129
+ "LOW": 0.3,
130
+ }
131
+ return mapping.get(confidence.upper(), 0.5)
132
+
133
+ def _create_finding(self, finding_data: dict[str, Any]):
134
+ """Create a Finding object from Bandit output."""
135
+ from patchi.core.security.tool_adapters import make_tool_finding
136
+
137
+ return make_tool_finding(
138
+ agent="BanditAgent",
139
+ ftype=finding_data.get("type", "bandit_finding"),
140
+ raw_severity=finding_data.get("severity", "MEDIUM"),
141
+ file=finding_data.get("file", ""),
142
+ line=finding_data.get("line", 0),
143
+ message=finding_data.get("message", ""),
144
+ cwe=finding_data.get("cwe", ""),
145
+ snippet=finding_data.get("snippet", ""),
146
+ confidence_raw=finding_data.get("confidence"),
147
+ extra={"more_info": finding_data.get("more_info", "")},
148
+ )
149
+
150
+
151
+ # Register the agent
152
+ register(BanditAgent)
@@ -0,0 +1,226 @@
1
+ """
2
+ Blast Radius Simulation (Layer 6) — prevents cascade breakage from fixes.
3
+
4
+ Three signals:
5
+ 1. Static blast radius — count references to symbol/package being changed
6
+ 2. Dependency tree dry-run — npm install --dry-run diff
7
+ 3. Behavioral diff — browser baseline → sandbox fix → re-run → diff
8
+
9
+ The apply gate combines all three into auto-apply / stop-and-report.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import re
16
+ import subprocess
17
+ from pathlib import Path
18
+
19
+ from patchi.core.agents.base import (
20
+ AgentGroup,
21
+ AgentInput,
22
+ AgentResult,
23
+ BaseAgent,
24
+ Finding,
25
+ Severity,
26
+ register,
27
+ safe_rglob,
28
+ )
29
+
30
+ # ── Static blast radius ───────────────────────────────────────────────────────
31
+
32
+
33
+ def patchi_blast_radius(symbol_or_package: str, root: Path) -> dict:
34
+ """
35
+ Count references to a symbol or package across the codebase.
36
+ Returns count + list of referencing files.
37
+ """
38
+ refs = []
39
+ re_pattern = re.compile(re.escape(symbol_or_package))
40
+
41
+ source_patterns = [
42
+ "*.py",
43
+ "*.pyw",
44
+ "*.js",
45
+ "*.mjs",
46
+ "*.cjs",
47
+ "*.jsx",
48
+ "*.ts",
49
+ "*.tsx",
50
+ "*.mts",
51
+ "*.java",
52
+ "*.cs",
53
+ "*.rb",
54
+ "*.go",
55
+ "*.rs",
56
+ "*.cpp",
57
+ "*.cxx",
58
+ "*.cc",
59
+ "*.c",
60
+ "*.h",
61
+ "*.hpp",
62
+ "*.kt",
63
+ "*.swift",
64
+ "*.dart",
65
+ "*.php",
66
+ "*.php3",
67
+ "*.php4",
68
+ "*.php5",
69
+ "*.phtml",
70
+ "*.scala",
71
+ "*.svelte",
72
+ ]
73
+
74
+ for sp in source_patterns:
75
+ for fpath in safe_rglob(root, sp):
76
+ if not fpath.is_file():
77
+ continue
78
+ try:
79
+ content = fpath.read_text(encoding="utf-8", errors="ignore")
80
+ except OSError:
81
+ continue
82
+ if re_pattern.search(content):
83
+ refs.append(str(fpath.relative_to(root)))
84
+
85
+ return {
86
+ "symbol": symbol_or_package,
87
+ "reference_count": len(refs),
88
+ "referencing_files": refs,
89
+ "blast_level": "low" if len(refs) <= 3 else ("medium" if len(refs) <= 10 else "high"),
90
+ }
91
+
92
+
93
+ # ── Dependency tree dry-run ───────────────────────────────────────────────────
94
+
95
+
96
+ def patchi_dependency_dry_run(root: Path) -> dict:
97
+ """
98
+ Run npm install --dry-run or pip install --dry-run and return the diff.
99
+ """
100
+ result = {"tool": "", "would_install": [], "would_remove": [], "peer_warnings": []}
101
+
102
+ # Check for package.json (npm)
103
+ if (root / "package.json").exists():
104
+ try:
105
+ proc = subprocess.run(
106
+ ["npm", "install", "--dry-run", "--json"],
107
+ capture_output=True,
108
+ text=True,
109
+ timeout=30,
110
+ cwd=str(root),
111
+ )
112
+ result["tool"] = "npm"
113
+ if proc.stdout.strip():
114
+ try:
115
+ data = json.loads(proc.stdout)
116
+ # Parse npm dry-run output
117
+ if isinstance(data, dict):
118
+ result["would_install"] = list(data.get("added", []))
119
+ result["would_remove"] = list(data.get("removed", []))
120
+ except json.JSONDecodeError:
121
+ pass
122
+ except (FileNotFoundError, subprocess.TimeoutExpired):
123
+ pass
124
+
125
+ # Check for requirements.txt (pip)
126
+ elif (root / "requirements.txt").exists():
127
+ try:
128
+ proc = subprocess.run(
129
+ ["pip", "install", "--dry-run", "-r", "requirements.txt"],
130
+ capture_output=True,
131
+ text=True,
132
+ timeout=30,
133
+ cwd=str(root),
134
+ )
135
+ result["tool"] = "pip"
136
+ # Parse pip dry-run output
137
+ for line in proc.stdout.splitlines():
138
+ if "Would install" in line:
139
+ result["would_install"] = line.replace("Would install", "").strip().split()
140
+ elif "Would remove" in line:
141
+ result["would_remove"] = line.replace("Would remove", "").strip().split()
142
+ except (FileNotFoundError, subprocess.TimeoutExpired):
143
+ pass
144
+
145
+ result["total_changes"] = len(result["would_install"]) + len(result["would_remove"])
146
+ return result
147
+
148
+
149
+ # ── Apply gate ────────────────────────────────────────────────────────────────
150
+
151
+
152
+ def patchi_apply_gate(static_radius: dict, dep_diff: dict) -> dict:
153
+ """
154
+ Combine signals into an auto-apply / stop-and-report decision.
155
+ """
156
+ blast_level = static_radius.get("blast_level", "low")
157
+ dep_changes = dep_diff.get("total_changes", 0)
158
+
159
+ if blast_level == "low" and dep_changes == 0:
160
+ return {
161
+ "decision": "auto_apply",
162
+ "reason": "Low blast radius, no dependency changes",
163
+ "blast_level": blast_level,
164
+ "dep_changes": dep_changes,
165
+ }
166
+ else:
167
+ return {
168
+ "decision": "require_review",
169
+ "reason": f"Blast radius: {blast_level}, dependency changes: {dep_changes}",
170
+ "blast_level": blast_level,
171
+ "dep_changes": dep_changes,
172
+ "referencing_files": static_radius.get("referencing_files", []),
173
+ "would_install": dep_diff.get("would_install", []),
174
+ "would_remove": dep_diff.get("would_remove", []),
175
+ }
176
+
177
+
178
+ # ── Blast Radius Agent ───────────────────────────────────────────────────────
179
+
180
+
181
+ @register
182
+ class BlastRadiusAgent(BaseAgent):
183
+ """Computes blast radius for proposed fixes and dependency changes."""
184
+
185
+ name = "BlastRadiusAgent"
186
+ group = AgentGroup.GUARD
187
+ timeout = 60
188
+
189
+ def _run(self, inp: AgentInput, result: AgentResult) -> None:
190
+ # Get findings that need blast radius analysis
191
+ findings = inp.extra.get("findings", [])
192
+ high_risk_findings = [f for f in findings if f.get("severity") in ("critical", "high")]
193
+
194
+ for finding in high_risk_findings[:5]:
195
+ fpath = finding.get("file", "")
196
+ if not fpath:
197
+ continue
198
+
199
+ # Static blast radius
200
+ symbol = Path(fpath).stem
201
+ radius = patchi_blast_radius(symbol, inp.root)
202
+
203
+ # Dependency dry-run if it's a dependency fix
204
+ dep_diff = {"total_changes": 0, "tool": ""}
205
+ if finding.get("type") in ("vulnerable_dependency", "unpinned_dependency"):
206
+ dep_diff = patchi_dependency_dry_run(inp.root)
207
+
208
+ gate = patchi_apply_gate(radius, dep_diff)
209
+
210
+ finding["blast_radius"] = radius
211
+ finding["dep_diff"] = dep_diff
212
+ finding["apply_gate"] = gate
213
+
214
+ if gate["decision"] == "require_review":
215
+ result.add_finding(
216
+ Finding(
217
+ agent=self.name,
218
+ type="high_blast_radius",
219
+ severity=Severity.HIGH,
220
+ file=fpath,
221
+ message=f"Fix requires review: {gate['reason']}",
222
+ detail=json.dumps(gate, indent=2),
223
+ )
224
+ )
225
+
226
+ result.data["analyzed_count"] = min(len(high_risk_findings), 5)