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,327 @@
1
+ """
2
+ `p chains` — Unified exploit chain analysis.
3
+
4
+ Combines the original `p chain` (analyze findings) and `p chains` (show persisted chains)
5
+ into a single command.
6
+
7
+ Usage:
8
+ p chains — show persisted chains + intent gaps
9
+ p chains --analyze — analyze findings from memory (like old p chain)
10
+ p chains --json — machine-readable output
11
+ p chains --min-score 50 — filter chains by minimum score
12
+ p chains --fix — apply auto-fixable remediations
13
+ p chains --min-severity high — filter by severity (with --analyze)
14
+
15
+ Exit codes:
16
+ 0 — no chains found
17
+ 1 — chains found
18
+ 2 — no data to analyze
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import json
24
+ import logging
25
+ from pathlib import Path
26
+
27
+ from rich.table import Table
28
+
29
+ from patchi.cli.console import con
30
+ from patchi.core.config import require_project_root
31
+
32
+ _log = logging.getLogger("patchi.cli.chains_cmd")
33
+
34
+
35
+ def run(
36
+ min_score: float = 0,
37
+ json_output: bool = False,
38
+ root: Path | None = None,
39
+ fix: bool = False,
40
+ analyze: bool = False,
41
+ min_severity: str = "medium",
42
+ ) -> None:
43
+ """Entry point for `p chains`."""
44
+ try:
45
+ r = root or require_project_root()
46
+ except RuntimeError as e:
47
+ con.print(f"[red]{e}[/red]")
48
+ return
49
+
50
+ # --analyze mode: analyze findings from memory (like old p chain)
51
+ if analyze:
52
+ _analyze_findings(r, min_severity, json_output)
53
+ return
54
+
55
+ # Default mode: show persisted chains from chain_intent.json
56
+ ci_path = r / ".patchi" / "chain_intent.json"
57
+ if not ci_path.is_file():
58
+ con.print("[yellow]No chain/intent data found.[/yellow]")
59
+ con.print(
60
+ "[dim]Run [bold]p scan[/bold] first to generate chains, "
61
+ "or use [bold]p chains --analyze[/bold] to analyze from findings.[/dim]"
62
+ )
63
+ return
64
+
65
+ try:
66
+ data = json.loads(ci_path.read_text(encoding="utf-8"))
67
+ except Exception as e:
68
+ con.print(f"[red]Failed to load chain data: {e}[/red]")
69
+ return
70
+
71
+ chains = data.get("chains", [])
72
+ intent = data.get("intent_report")
73
+
74
+ if not chains and not intent:
75
+ con.print("[dim]No exploit chains or intent gaps found in last scan.[/dim]")
76
+ return
77
+
78
+ # Filter by min score
79
+ if min_score > 0:
80
+ chains = [c for c in chains if c.get("score", 0) >= min_score]
81
+
82
+ # --fix mode: apply auto-fixable remediations via RiskGate
83
+ if fix:
84
+ _apply_fixes(r, chains, con)
85
+ return
86
+
87
+ if json_output:
88
+ _print_json(chains, intent)
89
+ return
90
+
91
+ # ── Rich output ───────────────────────────────────────────────────────
92
+ con.print()
93
+ con.print("[bold #C8621A]── Exploit Chains & Intent Gaps ──[/bold #C8621A]")
94
+ con.print()
95
+
96
+ # Chains table
97
+ if chains:
98
+ con.print(f"[bold]Exploit Chains[/bold] ({len(chains)})")
99
+ con.print()
100
+
101
+ table = Table(show_header=True, header_style="bold #C8621A", box=None)
102
+ table.add_column("#", style="dim", width=3)
103
+ table.add_column("Severity", width=10)
104
+ table.add_column("Score", justify="right", width=6)
105
+ table.add_column("Steps", justify="right", width=5)
106
+ table.add_column("Narrative")
107
+
108
+ for i, chain in enumerate(chains, 1):
109
+ sev = chain.get("severity", "info")
110
+ score = chain.get("score", 0)
111
+ length = chain.get("length", 0)
112
+ narrative = chain.get("narrative", "")
113
+
114
+ sev_color = {
115
+ "critical": "red bold",
116
+ "high": "red",
117
+ "medium": "yellow",
118
+ "low": "dim",
119
+ }.get(sev, "dim")
120
+
121
+ table.add_row(
122
+ str(i),
123
+ f"[{sev_color}]{sev}[/{sev_color}]",
124
+ f"{score:.0f}",
125
+ str(length),
126
+ narrative[:90],
127
+ )
128
+
129
+ con.print(table)
130
+ con.print()
131
+
132
+ # Show step details for top chains
133
+ for i, chain in enumerate(chains[:3], 1):
134
+ steps = chain.get("steps", [])
135
+ if steps:
136
+ con.print(f" [dim]Chain #{i} steps:[/dim]")
137
+ for step in steps:
138
+ role = step.get("role", "?")
139
+ ftype = step.get("type", "?")
140
+ file_ = step.get("file", "?")
141
+ line = step.get("line", "?")
142
+ sev = step.get("severity", "info")
143
+ con.print(f" [{sev}] [{role}] {ftype} @ {file_}:{line}")
144
+ con.print()
145
+ else:
146
+ con.print("[dim]No exploit chains found.[/dim]")
147
+ con.print()
148
+
149
+ # Intent gaps
150
+ if intent and intent.get("gaps_total", 0) > 0:
151
+ con.print(
152
+ f"[bold]Intent Gaps[/bold] ({intent['gaps_total']} across {intent.get('routes_total', '?')} routes)"
153
+ )
154
+ con.print()
155
+
156
+ for category, label, color in [
157
+ ("unauthenticated_state_changing", "Unauthenticated state-changing routes", "red"),
158
+ ("admin_without_strict_guard", "Admin routes without strict guard", "yellow"),
159
+ ("unprotected_among_protected", "Unprotected routes among protected peers", "yellow"),
160
+ ]:
161
+ routes = intent.get(category, [])
162
+ if routes:
163
+ con.print(f" [{color}]● {label} ({len(routes)})[/{color}]")
164
+ for r in routes[:5]:
165
+ method = r.get("method", "?")
166
+ path = r.get("path", "?")
167
+ file_ = r.get("file", "?")
168
+ line = r.get("line", "?")
169
+ has_guard = r.get("has_auth_guard", False)
170
+ guard_icon = "✓" if has_guard else "✗"
171
+ con.print(f" [{color}]{method}[/{color}] {path} [dim]{file_}:{line}[/dim] {guard_icon}")
172
+ if len(routes) > 5:
173
+ con.print(f" [dim]... and {len(routes) - 5} more[/dim]")
174
+ con.print()
175
+
176
+ con.print("[dim]Full detail: p chains --json | jq '.chains'[/dim]")
177
+ con.print()
178
+
179
+
180
+ def _analyze_findings(
181
+ root: Path, min_severity: str, json_output: bool, max_chains: int = 20
182
+ ) -> None:
183
+ """Analyze findings from memory (original p chain behavior)."""
184
+ from patchi.core import memory as mem
185
+
186
+ stored = mem.load_scan_results(root)
187
+ if not stored:
188
+ con.print("[yellow]No findings in memory. Run `p scan` first.[/yellow]")
189
+ return
190
+
191
+ # Rehydrate Finding-like objects from stored dicts.
192
+ from patchi.core.agents.base import Finding, Severity
193
+
194
+ findings: list[Finding] = []
195
+ for result in stored.values():
196
+ data = result.get("findings") or result if isinstance(result, dict) else {}
197
+ items = data if isinstance(data, list) else (data.get("findings") or [])
198
+ for f in items:
199
+ try:
200
+ findings.append(
201
+ Finding(
202
+ agent=f.get("agent", "?"),
203
+ type=f.get("type", "unknown"),
204
+ severity=Severity(f.get("severity", "medium")),
205
+ file=f.get("file", ""),
206
+ line=int(f.get("line", 0)),
207
+ message=f.get("message", ""),
208
+ cwe=f.get("cwe", ""),
209
+ )
210
+ )
211
+ except (ValueError, KeyError):
212
+ continue
213
+
214
+ if not findings:
215
+ con.print("[yellow]No findings in memory. Run `p scan` first.[/yellow]")
216
+ return
217
+
218
+ from patchi.core.security.attack_tree import build_attack_trees
219
+ from patchi.core.security.chain_analyzer import ChainAnalyzer
220
+
221
+ analyzer = ChainAnalyzer(findings)
222
+ chains = analyzer.find_chains(max_chains=max_chains)
223
+ trees = build_attack_trees(chains)
224
+
225
+ order = {"info": 0, "low": 1, "medium": 2, "high": 3, "critical": 4}
226
+ floor = order.get(min_severity.lower(), 2)
227
+ visible = [c for c in chains if order.get(c.severity, 0) >= floor]
228
+
229
+ if json_output:
230
+ payload = {
231
+ "chains": [c.to_dict() for c in visible],
232
+ "trees": [t.to_dict() for t in trees],
233
+ "summary": analyzer.summary(),
234
+ }
235
+ import sys
236
+
237
+ sys.stdout.write(json.dumps(payload, indent=2, default=str) + "\n")
238
+ return
239
+
240
+ con.print()
241
+ con.print(
242
+ f"[bold #C8621A]Exploit Chain Analysis[/bold #C8621A] "
243
+ f"[dim]{len(findings)} findings -> {len(chains)} chains "
244
+ f"({len(visible)} >= {min_severity})[/dim]"
245
+ )
246
+ con.print()
247
+
248
+ if not chains:
249
+ con.print("[#4ADE80]No multi-step attack chains detected.[/#4ADE80]")
250
+ con.print("[dim]Individual findings still apply — see `p security`.[/dim]")
251
+ con.print()
252
+ con.print("[bold]Suggestions:[/bold]")
253
+ con.print(" • [dim]Run `p scan` to generate fresh findings[/dim]")
254
+ con.print(" • [dim]Run `p findings --json` to see raw findings[/dim]")
255
+ con.print(" • [dim]Run `p assure --run-attackers` for adversarial testing[/dim]")
256
+ return
257
+
258
+ table = Table(show_header=True, header_style="bold #C8621A", box=None, pad_edge=False)
259
+ table.add_column("#", width=4)
260
+ table.add_column("Sev", width=9)
261
+ table.add_column("Score", justify="right", width=6)
262
+ table.add_column("Chain")
263
+ for i, c in enumerate(visible, 1):
264
+ color = {"critical": "#FF4D6D", "high": "#FF8C42", "medium": "#FACC15"}.get(
265
+ c.severity, "#B8A898"
266
+ )
267
+ table.add_row(
268
+ str(i),
269
+ f"[{color}]{c.severity}[/{color}]",
270
+ f"{c.score:.0f}",
271
+ c.narrative[:120],
272
+ )
273
+ con.print(table)
274
+
275
+ if trees:
276
+ con.print()
277
+ for tree in trees[:3]:
278
+ con.print(f"[dim]{tree.render()}[/dim]")
279
+ con.print()
280
+
281
+ con.print("[dim]Full detail: p chains --json | jq '.chains'[/dim]")
282
+ con.print()
283
+
284
+
285
+ def _print_json(chains: list, intent: dict | None) -> None:
286
+ """Print chains and intent data as JSON."""
287
+ payload = {"chains": chains, "intent_report": intent}
288
+ con.print(json.dumps(payload, indent=2, default=str))
289
+
290
+
291
+ def _apply_fixes(root: Path, chains: list[dict], con) -> None:
292
+ """Apply auto-fixable remediations from chain data."""
293
+ from patchi.core.fix.risk_gate import RiskGate
294
+
295
+ gate = RiskGate(root)
296
+ applied = 0
297
+ blocked = 0
298
+
299
+ for chain in chains:
300
+ for step in chain.get("steps", []):
301
+ if not step.get("remediation"):
302
+ continue
303
+ rem = step["remediation"]
304
+ if not rem.get("auto_fixable"):
305
+ continue
306
+
307
+ file_ = step.get("file", "")
308
+ if not file_:
309
+ continue
310
+
311
+ # Try to apply
312
+ decision = gate.evaluate(
313
+ action="auto_fix",
314
+ file_path=file_,
315
+ description=rem.get("description", ""),
316
+ confidence=rem.get("confidence", 0.5),
317
+ )
318
+
319
+ if decision.approved:
320
+ applied += 1
321
+ con.print(f"[green]✓[/green] {file_}: {rem.get('action', 'fixed')}")
322
+ else:
323
+ blocked += 1
324
+ con.print(f"[yellow]✗[/yellow] {file_}: blocked by RiskGate — {decision.reason}")
325
+
326
+ con.print()
327
+ con.print(f"[bold]Applied: {applied}, Blocked: {blocked}[/bold]")
@@ -0,0 +1,173 @@
1
+ """
2
+ CLI command for the project Charter — guard rails.
3
+
4
+ Subcommands:
5
+ p charter show Show current charter
6
+ p charter set "<text>" Set charter from natural language
7
+ p charter check Check code against charter
8
+ p charter hooks --install Manage git hooks
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import logging
15
+ import sys
16
+
17
+ _log = logging.getLogger("patchi.cli.commands.charter_cmd")
18
+
19
+
20
+
21
+ def _get_root():
22
+ from patchi.core.config import require_project_root
23
+ return require_project_root()
24
+
25
+
26
+ def run_show(args) -> None:
27
+ """Show the current charter."""
28
+ root = _get_root()
29
+ from patchi.core.security.charter import load_charter
30
+
31
+ charter = load_charter(root)
32
+ json_output = getattr(args, "json_output", False)
33
+
34
+ if not charter.text and not charter.rules:
35
+ return
36
+
37
+ if json_output:
38
+ pass
39
+ else:
40
+ if charter.text:
41
+ pass
42
+ for _r in charter.rules:
43
+ pass
44
+
45
+
46
+ def run_set(args) -> None:
47
+ """Set charter from natural language text."""
48
+ text = getattr(args, "text", None)
49
+ if not text:
50
+ sys.exit(1)
51
+
52
+ root = _get_root()
53
+ from patchi.core.security.charter import (
54
+ Charter,
55
+ parse_nl_to_rules,
56
+ save_charter,
57
+ )
58
+
59
+ rules = parse_nl_to_rules(text)
60
+ charter = Charter(text=text, rules=rules)
61
+ save_charter(charter, root)
62
+ for _r in rules:
63
+ pass
64
+
65
+
66
+ def run_check(args) -> None:
67
+ """Check codebase against the charter."""
68
+ root = _get_root()
69
+ from patchi.core.security.charter import (
70
+ check_all_violations,
71
+ load_charter,
72
+ )
73
+
74
+ charter = load_charter(root)
75
+ if not charter.rules:
76
+ return
77
+
78
+ # Try to get import edges from the brain
79
+ import_edges: list[tuple[str, str]] = []
80
+ try:
81
+ graph_path = root / ".patchi" / "memory" / "import_graph.json"
82
+ if graph_path.exists():
83
+ data = json.loads(graph_path.read_text(encoding="utf-8"))
84
+ edges = data.get("edges", [])
85
+ for e in edges:
86
+ if isinstance(e, dict):
87
+ import_edges.append((e.get("source", ""), e.get("target", "")))
88
+ elif isinstance(e, (list, tuple)) and len(e) >= 2:
89
+ import_edges.append((str(e[0]), str(e[1])))
90
+ except Exception as _exc:
91
+ _log.warning('run_check failed: %s', _exc)
92
+
93
+ violations = check_all_violations(charter, import_edges=import_edges)
94
+
95
+ json_output = getattr(args, "json_output", False)
96
+ if json_output:
97
+ pass
98
+ else:
99
+ if not violations:
100
+ pass
101
+ else:
102
+ for v in violations:
103
+ if v.suggestion:
104
+ pass
105
+
106
+ sys.exit(1 if violations else 0)
107
+
108
+
109
+ def run_hooks(args) -> None:
110
+ """Manage charter-related git hooks."""
111
+ install = getattr(args, "install", False)
112
+
113
+ if not install:
114
+ return
115
+
116
+ root = _get_root()
117
+ hooks_dir = root / ".git" / "hooks"
118
+ if not hooks_dir.exists():
119
+ sys.exit(1)
120
+
121
+ hook_path = hooks_dir / "charter-check"
122
+ hook_body = """#!/bin/sh
123
+ # Patchi Charter check hook — runs after pre-commit
124
+ # Checks staged files against the project charter
125
+
126
+ PATCHI_DIR="$(git rev-parse --show-toplevel)"
127
+
128
+ # Only check .py, .ts, .js, .go, .java, .rs files
129
+ STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(py|ts|js|go|java|rs)$')
130
+
131
+ if [ -z "$STAGED" ]; then
132
+ exit 0
133
+ fi
134
+
135
+ cd "$PATCHI_DIR" && python -m patchi.cli.main charter check 2>/dev/null
136
+ STATUS=$?
137
+ if [ $STATUS -ne 0 ]; then
138
+ echo ""
139
+ echo "⚠ Charter violations detected. Fix before committing."
140
+ echo " Run 'p charter check' for details."
141
+ echo " Bypass with: git commit --no-verify"
142
+ fi
143
+ exit 0
144
+ """
145
+ hook_path.write_text(hook_body, encoding="utf-8")
146
+ # Make executable on Unix
147
+ import stat
148
+ hook_path.chmod(hook_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
149
+
150
+
151
+
152
+ # Backward compat entry point
153
+ def run(args) -> None:
154
+ """Dispatch to the appropriate subcommand."""
155
+ if hasattr(args, "action"):
156
+ action = args.action
157
+ elif isinstance(args, list) and args:
158
+ action = args[0]
159
+ else:
160
+ action = "show"
161
+
162
+ dispatch = {
163
+ "show": run_show,
164
+ "set": run_set,
165
+ "check": run_check,
166
+ "hooks": run_hooks,
167
+ }
168
+
169
+ handler = dispatch.get(action)
170
+ if handler:
171
+ handler(args)
172
+ else:
173
+ sys.exit(1)