souleyez 2.43.26__py3-none-any.whl → 2.43.34__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.

Potentially problematic release.


This version of souleyez might be problematic. Click here for more details.

Files changed (358) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9526 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1239 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2200 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +292 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/web_login_test_handler.py +327 -0
  126. souleyez/handlers/whois_handler.py +277 -0
  127. souleyez/handlers/wpscan_handler.py +554 -0
  128. souleyez/history.py +32 -16
  129. souleyez/importers/msf_importer.py +106 -75
  130. souleyez/importers/smart_importer.py +208 -147
  131. souleyez/integrations/siem/__init__.py +10 -10
  132. souleyez/integrations/siem/base.py +17 -18
  133. souleyez/integrations/siem/elastic.py +108 -122
  134. souleyez/integrations/siem/factory.py +207 -80
  135. souleyez/integrations/siem/googlesecops.py +146 -154
  136. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  137. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  138. souleyez/integrations/siem/sentinel.py +107 -109
  139. souleyez/integrations/siem/splunk.py +246 -212
  140. souleyez/integrations/siem/wazuh.py +65 -71
  141. souleyez/integrations/wazuh/__init__.py +5 -5
  142. souleyez/integrations/wazuh/client.py +70 -93
  143. souleyez/integrations/wazuh/config.py +85 -57
  144. souleyez/integrations/wazuh/host_mapper.py +28 -36
  145. souleyez/integrations/wazuh/sync.py +78 -68
  146. souleyez/intelligence/__init__.py +4 -5
  147. souleyez/intelligence/correlation_analyzer.py +309 -295
  148. souleyez/intelligence/exploit_knowledge.py +661 -623
  149. souleyez/intelligence/exploit_suggestions.py +159 -139
  150. souleyez/intelligence/gap_analyzer.py +132 -97
  151. souleyez/intelligence/gap_detector.py +251 -214
  152. souleyez/intelligence/sensitive_tables.py +266 -129
  153. souleyez/intelligence/service_parser.py +137 -123
  154. souleyez/intelligence/surface_analyzer.py +407 -268
  155. souleyez/intelligence/target_parser.py +159 -162
  156. souleyez/licensing/__init__.py +6 -6
  157. souleyez/licensing/validator.py +17 -19
  158. souleyez/log_config.py +79 -54
  159. souleyez/main.py +1505 -687
  160. souleyez/migrations/fix_job_counter.py +16 -14
  161. souleyez/parsers/bloodhound_parser.py +41 -39
  162. souleyez/parsers/crackmapexec_parser.py +178 -111
  163. souleyez/parsers/dalfox_parser.py +72 -77
  164. souleyez/parsers/dnsrecon_parser.py +103 -91
  165. souleyez/parsers/enum4linux_parser.py +183 -153
  166. souleyez/parsers/ffuf_parser.py +29 -25
  167. souleyez/parsers/gobuster_parser.py +301 -41
  168. souleyez/parsers/hashcat_parser.py +324 -79
  169. souleyez/parsers/http_fingerprint_parser.py +350 -103
  170. souleyez/parsers/hydra_parser.py +131 -111
  171. souleyez/parsers/impacket_parser.py +231 -178
  172. souleyez/parsers/john_parser.py +98 -86
  173. souleyez/parsers/katana_parser.py +316 -0
  174. souleyez/parsers/msf_parser.py +943 -498
  175. souleyez/parsers/nikto_parser.py +346 -65
  176. souleyez/parsers/nmap_parser.py +262 -174
  177. souleyez/parsers/nuclei_parser.py +40 -44
  178. souleyez/parsers/responder_parser.py +26 -26
  179. souleyez/parsers/searchsploit_parser.py +74 -74
  180. souleyez/parsers/service_explorer_parser.py +279 -0
  181. souleyez/parsers/smbmap_parser.py +180 -124
  182. souleyez/parsers/sqlmap_parser.py +434 -308
  183. souleyez/parsers/theharvester_parser.py +75 -57
  184. souleyez/parsers/whois_parser.py +135 -94
  185. souleyez/parsers/wpscan_parser.py +278 -190
  186. souleyez/plugins/afp.py +44 -36
  187. souleyez/plugins/afp_brute.py +114 -46
  188. souleyez/plugins/ard.py +48 -37
  189. souleyez/plugins/bloodhound.py +95 -61
  190. souleyez/plugins/certipy.py +303 -0
  191. souleyez/plugins/crackmapexec.py +186 -85
  192. souleyez/plugins/dalfox.py +120 -59
  193. souleyez/plugins/dns_hijack.py +146 -41
  194. souleyez/plugins/dnsrecon.py +97 -61
  195. souleyez/plugins/enum4linux.py +91 -66
  196. souleyez/plugins/evil_winrm.py +291 -0
  197. souleyez/plugins/ffuf.py +166 -90
  198. souleyez/plugins/firmware_extract.py +133 -29
  199. souleyez/plugins/gobuster.py +387 -190
  200. souleyez/plugins/gpp_extract.py +393 -0
  201. souleyez/plugins/hashcat.py +100 -73
  202. souleyez/plugins/http_fingerprint.py +854 -267
  203. souleyez/plugins/hydra.py +566 -200
  204. souleyez/plugins/impacket_getnpusers.py +117 -69
  205. souleyez/plugins/impacket_psexec.py +84 -64
  206. souleyez/plugins/impacket_secretsdump.py +103 -69
  207. souleyez/plugins/impacket_smbclient.py +89 -75
  208. souleyez/plugins/john.py +86 -69
  209. souleyez/plugins/katana.py +313 -0
  210. souleyez/plugins/kerbrute.py +237 -0
  211. souleyez/plugins/lfi_extract.py +541 -0
  212. souleyez/plugins/macos_ssh.py +117 -48
  213. souleyez/plugins/mdns.py +35 -30
  214. souleyez/plugins/msf_auxiliary.py +253 -130
  215. souleyez/plugins/msf_exploit.py +239 -161
  216. souleyez/plugins/nikto.py +134 -78
  217. souleyez/plugins/nmap.py +275 -91
  218. souleyez/plugins/nuclei.py +180 -89
  219. souleyez/plugins/nxc.py +285 -0
  220. souleyez/plugins/plugin_base.py +35 -36
  221. souleyez/plugins/plugin_template.py +13 -5
  222. souleyez/plugins/rdp_sec_check.py +130 -0
  223. souleyez/plugins/responder.py +112 -71
  224. souleyez/plugins/router_http_brute.py +76 -65
  225. souleyez/plugins/router_ssh_brute.py +118 -41
  226. souleyez/plugins/router_telnet_brute.py +124 -42
  227. souleyez/plugins/routersploit.py +91 -59
  228. souleyez/plugins/routersploit_exploit.py +77 -55
  229. souleyez/plugins/searchsploit.py +91 -77
  230. souleyez/plugins/service_explorer.py +1160 -0
  231. souleyez/plugins/smbmap.py +122 -72
  232. souleyez/plugins/smbpasswd.py +215 -0
  233. souleyez/plugins/sqlmap.py +301 -113
  234. souleyez/plugins/theharvester.py +127 -75
  235. souleyez/plugins/tr069.py +79 -57
  236. souleyez/plugins/upnp.py +65 -47
  237. souleyez/plugins/upnp_abuse.py +73 -55
  238. souleyez/plugins/vnc_access.py +129 -42
  239. souleyez/plugins/vnc_brute.py +109 -38
  240. souleyez/plugins/web_login_test.py +417 -0
  241. souleyez/plugins/whois.py +77 -58
  242. souleyez/plugins/wpscan.py +173 -69
  243. souleyez/reporting/__init__.py +2 -1
  244. souleyez/reporting/attack_chain.py +411 -346
  245. souleyez/reporting/charts.py +436 -501
  246. souleyez/reporting/compliance_mappings.py +334 -201
  247. souleyez/reporting/detection_report.py +126 -125
  248. souleyez/reporting/formatters.py +828 -591
  249. souleyez/reporting/generator.py +386 -302
  250. souleyez/reporting/metrics.py +72 -75
  251. souleyez/scanner.py +35 -29
  252. souleyez/security/__init__.py +37 -11
  253. souleyez/security/scope_validator.py +175 -106
  254. souleyez/security/validation.py +223 -149
  255. souleyez/security.py +22 -6
  256. souleyez/storage/credentials.py +247 -186
  257. souleyez/storage/crypto.py +296 -129
  258. souleyez/storage/database.py +73 -50
  259. souleyez/storage/db.py +58 -36
  260. souleyez/storage/deliverable_evidence.py +177 -128
  261. souleyez/storage/deliverable_exporter.py +282 -246
  262. souleyez/storage/deliverable_templates.py +134 -116
  263. souleyez/storage/deliverables.py +135 -130
  264. souleyez/storage/engagements.py +109 -56
  265. souleyez/storage/evidence.py +181 -152
  266. souleyez/storage/execution_log.py +31 -17
  267. souleyez/storage/exploit_attempts.py +93 -57
  268. souleyez/storage/exploits.py +67 -36
  269. souleyez/storage/findings.py +48 -61
  270. souleyez/storage/hosts.py +176 -144
  271. souleyez/storage/migrate_to_engagements.py +43 -19
  272. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  273. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  274. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  275. souleyez/storage/migrations/_005_screenshots.py +13 -5
  276. souleyez/storage/migrations/_006_deliverables.py +13 -5
  277. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  278. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  279. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  280. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  281. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  282. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  283. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  284. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  285. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  286. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  287. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  288. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  289. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  290. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  291. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  292. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  293. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  294. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  295. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  296. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  297. souleyez/storage/migrations/__init__.py +26 -26
  298. souleyez/storage/migrations/migration_manager.py +19 -19
  299. souleyez/storage/msf_sessions.py +100 -65
  300. souleyez/storage/osint.py +17 -24
  301. souleyez/storage/recommendation_engine.py +269 -235
  302. souleyez/storage/screenshots.py +33 -32
  303. souleyez/storage/smb_shares.py +136 -92
  304. souleyez/storage/sqlmap_data.py +183 -128
  305. souleyez/storage/team_collaboration.py +135 -141
  306. souleyez/storage/timeline_tracker.py +122 -94
  307. souleyez/storage/wazuh_vulns.py +64 -66
  308. souleyez/storage/web_paths.py +33 -37
  309. souleyez/testing/credential_tester.py +221 -205
  310. souleyez/ui/__init__.py +1 -1
  311. souleyez/ui/ai_quotes.py +12 -12
  312. souleyez/ui/attack_surface.py +2439 -1516
  313. souleyez/ui/chain_rules_view.py +914 -382
  314. souleyez/ui/correlation_view.py +312 -230
  315. souleyez/ui/dashboard.py +2382 -1130
  316. souleyez/ui/deliverables_view.py +148 -62
  317. souleyez/ui/design_system.py +13 -13
  318. souleyez/ui/errors.py +49 -49
  319. souleyez/ui/evidence_linking_view.py +284 -179
  320. souleyez/ui/evidence_vault.py +393 -285
  321. souleyez/ui/exploit_suggestions_view.py +555 -349
  322. souleyez/ui/export_view.py +100 -66
  323. souleyez/ui/gap_analysis_view.py +315 -171
  324. souleyez/ui/help_system.py +105 -97
  325. souleyez/ui/intelligence_view.py +436 -293
  326. souleyez/ui/interactive.py +23434 -10286
  327. souleyez/ui/interactive_selector.py +75 -68
  328. souleyez/ui/log_formatter.py +47 -39
  329. souleyez/ui/menu_components.py +22 -13
  330. souleyez/ui/msf_auxiliary_menu.py +184 -133
  331. souleyez/ui/pending_chains_view.py +336 -172
  332. souleyez/ui/progress_indicators.py +5 -3
  333. souleyez/ui/recommendations_view.py +195 -137
  334. souleyez/ui/rule_builder.py +343 -225
  335. souleyez/ui/setup_wizard.py +678 -284
  336. souleyez/ui/shortcuts.py +217 -165
  337. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  338. souleyez/ui/splunk_vulns_view.py +139 -86
  339. souleyez/ui/team_dashboard.py +498 -335
  340. souleyez/ui/template_selector.py +196 -105
  341. souleyez/ui/terminal.py +6 -6
  342. souleyez/ui/timeline_view.py +198 -127
  343. souleyez/ui/tool_setup.py +264 -164
  344. souleyez/ui/tutorial.py +202 -72
  345. souleyez/ui/tutorial_state.py +40 -40
  346. souleyez/ui/wazuh_vulns_view.py +235 -141
  347. souleyez/ui/wordlist_browser.py +260 -107
  348. souleyez/ui.py +464 -312
  349. souleyez/utils/tool_checker.py +427 -367
  350. souleyez/utils.py +33 -29
  351. souleyez/wordlists.py +134 -167
  352. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
  353. souleyez-2.43.34.dist-info/RECORD +443 -0
  354. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.26.dist-info/RECORD +0 -379
  356. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,10 @@
1
1
  """Deliverables dashboard view for interactive UI."""
2
+
2
3
  import click
3
4
  from rich.console import Console
4
5
  from rich.table import Table
5
6
  from rich.progress import Progress, BarColumn, TextColumn
7
+
6
8
  try:
7
9
  from rich.progress import TaskProgressColumn
8
10
  except ImportError:
@@ -32,98 +34,155 @@ def show_deliverables_dashboard(engagement_id):
32
34
  # Header
33
35
  width = DesignSystem.get_terminal_width()
34
36
  click.echo("\n┌" + "─" * (width - 2) + "┐")
35
- click.echo("│" + click.style(" DELIVERABLES & ACCEPTANCE CRITERIA ".center(width - 2), bold=True, fg='cyan') + "│")
37
+ click.echo(
38
+ "│"
39
+ + click.style(
40
+ " DELIVERABLES & ACCEPTANCE CRITERIA ".center(width - 2),
41
+ bold=True,
42
+ fg="cyan",
43
+ )
44
+ + "│"
45
+ )
36
46
  click.echo("└" + "─" * (width - 2) + "┘")
37
47
  click.echo()
38
48
 
39
49
  # Summary
40
50
  summary = dm.get_summary(engagement_id)
41
51
 
42
- if summary['total'] == 0:
52
+ if summary["total"] == 0:
43
53
  # Go directly to template selector when no deliverables exist
44
54
  from souleyez.ui.template_selector import show_template_selector
55
+
45
56
  loaded = show_template_selector(engagement_id)
46
57
  if loaded:
47
58
  continue # Reload deliverables view
48
59
  break # Back if cancelled
49
60
 
50
61
  click.echo(f" Engagement: {current['name']}")
51
- click.echo(f" Overall Progress: {summary['completed']}/{summary['total']} deliverables ({summary['completion_rate']*100:.0f}%)")
62
+ click.echo(
63
+ f" Overall Progress: {summary['completed']}/{summary['total']} deliverables ({summary['completion_rate']*100:.0f}%)"
64
+ )
52
65
  click.echo()
53
66
 
54
67
  # Progress bar
55
68
  bar_width = min(50, width - 30)
56
- completed = summary['completed']
57
- total = summary['total'] if summary['total'] > 0 else 1
69
+ completed = summary["completed"]
70
+ total = summary["total"] if summary["total"] > 0 else 1
58
71
  filled = int((completed / total) * bar_width)
59
72
  bar = "█" * filled + "░" * (bar_width - filled)
60
-
73
+
61
74
  click.echo(f" Progress: [{bar}] {completed}/{total}")
62
75
  click.echo()
63
76
 
64
77
  # Deliverables by category
65
78
  deliverables = dm.list_deliverables(engagement_id)
66
79
 
67
- categories = ['reconnaissance', 'enumeration', 'exploitation', 'post_exploitation', 'techniques']
80
+ categories = [
81
+ "reconnaissance",
82
+ "enumeration",
83
+ "exploitation",
84
+ "post_exploitation",
85
+ "techniques",
86
+ ]
68
87
 
69
88
  for category in categories:
70
- cat_deliverables = [d for d in deliverables if d['category'] == category]
89
+ cat_deliverables = [d for d in deliverables if d["category"] == category]
71
90
 
72
91
  if not cat_deliverables:
73
92
  continue
74
93
 
75
- click.echo(click.style(f"\n {category.upper().replace('_', ' ')}", bold=True, fg='cyan'))
94
+ click.echo(
95
+ click.style(
96
+ f"\n {category.upper().replace('_', ' ')}", bold=True, fg="cyan"
97
+ )
98
+ )
76
99
  click.echo(" " + "─" * (width - 4))
77
100
 
78
101
  for d in cat_deliverables:
79
102
  # Status icon
80
103
  status_icon = {
81
- 'completed': '',
82
- 'in_progress': '🔄',
83
- 'pending': '⚠️',
84
- 'failed': ''
85
- }.get(d['status'], '?')
104
+ "completed": "",
105
+ "in_progress": "🔄",
106
+ "pending": "⚠️",
107
+ "failed": "",
108
+ }.get(d["status"], "?")
86
109
 
87
110
  # Progress
88
- if d['target_type'] == 'count':
89
- current_val = d['current_value'] or 0
90
- target_val = d['target_value']
111
+ if d["target_type"] == "count":
112
+ current_val = d["current_value"] or 0
113
+ target_val = d["target_value"]
91
114
  progress_str = f"[{current_val}/{target_val}]"
92
- elif d['target_type'] == 'boolean':
93
- progress_str = "[✓]" if d['status'] == 'completed' else "[✗]"
115
+ elif d["target_type"] == "boolean":
116
+ progress_str = "[✓]" if d["status"] == "completed" else "[✗]"
94
117
  else:
95
118
  progress_str = "[Manual]"
96
119
 
97
120
  # Priority color
98
121
  priority_styles = {
99
- 'critical': 'red',
100
- 'high': 'yellow',
101
- 'medium': 'white',
102
- 'low': 'bright_black'
122
+ "critical": "red",
123
+ "high": "yellow",
124
+ "medium": "white",
125
+ "low": "bright_black",
103
126
  }
104
- priority_color = priority_styles.get(d['priority'], 'white')
127
+ priority_color = priority_styles.get(d["priority"], "white")
105
128
 
106
- title_line = f" {status_icon} [{d['id']}] {d['title']} {progress_str}"
107
- if d['priority'] in ['critical', 'high']:
129
+ title_line = (
130
+ f" {status_icon} [{d['id']}] {d['title']} {progress_str}"
131
+ )
132
+ if d["priority"] in ["critical", "high"]:
108
133
  title_line = click.style(title_line, fg=priority_color)
109
-
134
+
110
135
  click.echo(title_line)
111
136
 
112
- if d['description'] and d['status'] != 'completed':
113
- click.echo(click.style(f" {d['description']}", fg='bright_black'))
137
+ if d["description"] and d["status"] != "completed":
138
+ click.echo(
139
+ click.style(f" {d['description']}", fg="bright_black")
140
+ )
114
141
 
115
142
  # Menu with standardized numbered options
116
143
  from souleyez.ui.menu_components import StandardMenu
117
144
 
118
145
  options = [
119
- {'number': 1, 'label': 'Validate All Deliverables', 'description': 'Auto-validate all deliverables based on evidence'},
120
- {'number': 2, 'label': 'Mark as Complete', 'description': 'Mark specific deliverable as complete'},
121
- {'number': 3, 'label': 'Link Evidence', 'description': 'Associate evidence with deliverable'},
122
- {'number': 4, 'label': 'View Timeline', 'description': 'Display timeline and velocity metrics'},
123
- {'number': 5, 'label': 'Export Deliverables', 'description': 'Generate deliverables report'},
124
- {'number': 6, 'label': 'Smart Recommendations', 'description': 'View AI-powered recommendations'},
125
- {'number': 7, 'label': 'Team Collaboration', 'description': 'Manage team assignments and status'},
126
- {'number': 8, 'label': 'Refresh View', 'description': 'Reload deliverables data'},
146
+ {
147
+ "number": 1,
148
+ "label": "Validate All Deliverables",
149
+ "description": "Auto-validate all deliverables based on evidence",
150
+ },
151
+ {
152
+ "number": 2,
153
+ "label": "Mark as Complete",
154
+ "description": "Mark specific deliverable as complete",
155
+ },
156
+ {
157
+ "number": 3,
158
+ "label": "Link Evidence",
159
+ "description": "Associate evidence with deliverable",
160
+ },
161
+ {
162
+ "number": 4,
163
+ "label": "View Timeline",
164
+ "description": "Display timeline and velocity metrics",
165
+ },
166
+ {
167
+ "number": 5,
168
+ "label": "Export Deliverables",
169
+ "description": "Generate deliverables report",
170
+ },
171
+ {
172
+ "number": 6,
173
+ "label": "Smart Recommendations",
174
+ "description": "View AI-powered recommendations",
175
+ },
176
+ {
177
+ "number": 7,
178
+ "label": "Team Collaboration",
179
+ "description": "Manage team assignments and status",
180
+ },
181
+ {
182
+ "number": 8,
183
+ "label": "Refresh View",
184
+ "description": "Reload deliverables data",
185
+ },
127
186
  ]
128
187
 
129
188
  choice = StandardMenu.render(options)
@@ -133,9 +192,11 @@ def show_deliverables_dashboard(engagement_id):
133
192
  elif choice == 1:
134
193
  # Validate
135
194
  click.echo()
136
- click.echo(click.style(" Validating all deliverables...", fg='cyan'))
195
+ click.echo(click.style(" Validating all deliverables...", fg="cyan"))
137
196
  stats = dm.validate_all(engagement_id)
138
- click.echo(click.style(f" ✓ Updated {stats['updated']} deliverables", fg='green'))
197
+ click.echo(
198
+ click.style(f" ✓ Updated {stats['updated']} deliverables", fg="green")
199
+ )
139
200
  click.echo(f" Completed: {stats['completed']}")
140
201
  click.echo(f" In Progress: {stats['in_progress']}")
141
202
  click.pause()
@@ -144,49 +205,67 @@ def show_deliverables_dashboard(engagement_id):
144
205
  from souleyez.ui.interactive_selector import interactive_select
145
206
 
146
207
  # Get incomplete deliverables
147
- incomplete = [d for d in deliverables if d['status'] != 'completed']
208
+ incomplete = [d for d in deliverables if d["status"] != "completed"]
148
209
 
149
210
  if not incomplete:
150
- click.echo(click.style("\n All deliverables are already completed!", fg='green'))
211
+ click.echo(
212
+ click.style(
213
+ "\n All deliverables are already completed!", fg="green"
214
+ )
215
+ )
151
216
  click.pause()
152
217
  continue
153
218
 
154
219
  selected_ids = set()
155
220
  columns = [
156
- {'name': 'ID', 'width': 6, 'key': 'id', 'justify': 'right'},
157
- {'name': 'Category', 'width': 15, 'key': 'category'},
158
- {'name': 'Status', 'width': 12, 'key': 'status'},
159
- {'name': 'Priority', 'width': 10, 'key': 'priority'},
160
- {'name': 'Title', 'key': 'title'},
221
+ {"name": "ID", "width": 6, "key": "id", "justify": "right"},
222
+ {"name": "Category", "width": 15, "key": "category"},
223
+ {"name": "Status", "width": 12, "key": "status"},
224
+ {"name": "Priority", "width": 10, "key": "priority"},
225
+ {"name": "Title", "key": "title"},
161
226
  ]
162
227
 
163
228
  def format_deliverable_cell(item: dict, key: str) -> str:
164
229
  value = item.get(key)
165
230
  if value is None:
166
- return '-'
167
- if key == 'status':
168
- colors = {'pending': 'yellow', 'in_progress': 'cyan', 'failed': 'red'}
169
- color = colors.get(value, 'white')
170
- return f'[{color}]{value}[/{color}]'
171
- if key == 'priority':
172
- colors = {'critical': 'red', 'high': 'yellow', 'medium': 'white', 'low': 'dim'}
173
- color = colors.get(value, 'white')
174
- return f'[{color}]{value}[/{color}]'
175
- return str(value) if value else '-'
231
+ return "-"
232
+ if key == "status":
233
+ colors = {
234
+ "pending": "yellow",
235
+ "in_progress": "cyan",
236
+ "failed": "red",
237
+ }
238
+ color = colors.get(value, "white")
239
+ return f"[{color}]{value}[/{color}]"
240
+ if key == "priority":
241
+ colors = {
242
+ "critical": "red",
243
+ "high": "yellow",
244
+ "medium": "white",
245
+ "low": "dim",
246
+ }
247
+ color = colors.get(value, "white")
248
+ return f"[{color}]{value}[/{color}]"
249
+ return str(value) if value else "-"
176
250
 
177
251
  interactive_select(
178
252
  items=incomplete,
179
253
  columns=columns,
180
254
  selected_ids=selected_ids,
181
- get_id=lambda d: d.get('id'),
182
- title='SELECT DELIVERABLES TO MARK COMPLETE',
183
- format_cell=format_deliverable_cell
255
+ get_id=lambda d: d.get("id"),
256
+ title="SELECT DELIVERABLES TO MARK COMPLETE",
257
+ format_cell=format_deliverable_cell,
184
258
  )
185
259
 
186
260
  if selected_ids:
187
261
  for did in selected_ids:
188
262
  dm.mark_complete(did)
189
- click.echo(click.style(f"\n ✓ Marked {len(selected_ids)} deliverable(s) as completed", fg='green'))
263
+ click.echo(
264
+ click.style(
265
+ f"\n ✓ Marked {len(selected_ids)} deliverable(s) as completed",
266
+ fg="green",
267
+ )
268
+ )
190
269
  else:
191
270
  click.echo("\n No deliverables selected.")
192
271
  click.pause()
@@ -196,29 +275,36 @@ def show_deliverables_dashboard(engagement_id):
196
275
  deliverable = dm.get_deliverable(deliverable_id)
197
276
  if deliverable:
198
277
  from souleyez.ui.evidence_linking_view import show_evidence_linking_view
278
+
199
279
  show_evidence_linking_view(deliverable_id)
200
280
  else:
201
- click.echo(click.style(f" Deliverable {deliverable_id} not found", fg='red'))
281
+ click.echo(
282
+ click.style(f" Deliverable {deliverable_id} not found", fg="red")
283
+ )
202
284
  click.pause()
203
285
  elif choice == 4:
204
286
  # View timeline and velocity
205
287
  from souleyez.ui.timeline_view import show_timeline_view
288
+
206
289
  show_timeline_view(engagement_id)
207
290
  elif choice == 5:
208
291
  # Export deliverables
209
292
  from souleyez.ui.export_view import show_export_view
293
+
210
294
  show_export_view(engagement_id)
211
295
  elif choice == 6:
212
296
  # Smart recommendations
213
297
  from souleyez.ui.recommendations_view import show_recommendations_dashboard
298
+
214
299
  show_recommendations_dashboard(engagement_id)
215
300
  elif choice == 7:
216
301
  # Team collaboration
217
302
  from souleyez.ui.team_dashboard import show_team_dashboard
303
+
218
304
  show_team_dashboard(engagement_id)
219
305
  elif choice == 8:
220
306
  # Refresh
221
307
  continue
222
308
  else:
223
- click.echo(click.style(" Invalid choice", fg='yellow'))
309
+ click.echo(click.style(" Invalid choice", fg="yellow"))
224
310
  click.pause()
@@ -16,19 +16,19 @@ class DesignSystem:
16
16
  """Centralized design system for SoulEyez UI."""
17
17
 
18
18
  # Box Styles
19
- HEADER_BOX = box.DOUBLE # ╔═╗ - App header only
20
- TABLE_BOX = box.SIMPLE # ─── - All tables
19
+ HEADER_BOX = box.DOUBLE # ╔═╗ - App header only
20
+ TABLE_BOX = box.SIMPLE # ─── - All tables
21
21
 
22
22
  # Widths
23
- DEFAULT_WIDTH = 100 # Default terminal width
24
- MIN_WIDTH = 80 # Minimum supported width
23
+ DEFAULT_WIDTH = 100 # Default terminal width
24
+ MIN_WIDTH = 80 # Minimum supported width
25
25
 
26
26
  # Separators
27
- SECTION_SEP = "─" # Section separator character
27
+ SECTION_SEP = "─" # Section separator character
28
28
 
29
29
  # Spacing
30
- SECTION_SPACING = 2 # Blank lines between sections
31
- CONTENT_SPACING = 1 # Blank lines after separator
30
+ SECTION_SPACING = 2 # Blank lines between sections
31
+ CONTENT_SPACING = 1 # Blank lines after separator
32
32
 
33
33
  @staticmethod
34
34
  def get_terminal_width() -> int:
@@ -44,7 +44,7 @@ class DesignSystem:
44
44
  """Generate section separator line."""
45
45
  w = width or DesignSystem.get_terminal_width()
46
46
  return DesignSystem.SECTION_SEP * w
47
-
47
+
48
48
  @staticmethod
49
49
  def clear_screen():
50
50
  """
@@ -57,10 +57,10 @@ class DesignSystem:
57
57
  import sys
58
58
 
59
59
  # Use system clear command - most reliable across all terminals
60
- if os.name == 'posix':
61
- os.system('clear')
60
+ if os.name == "posix":
61
+ os.system("clear")
62
62
  else:
63
- os.system('cls')
63
+ os.system("cls")
64
64
 
65
65
  @staticmethod
66
66
  def create_table(expand: bool = True, **kwargs) -> Table:
@@ -80,7 +80,7 @@ class DesignSystem:
80
80
  padding=(0, 1),
81
81
  show_header=True,
82
82
  header_style="bold",
83
- **kwargs
83
+ **kwargs,
84
84
  )
85
85
 
86
86
  @staticmethod
@@ -100,7 +100,7 @@ class DesignSystem:
100
100
  lines = [
101
101
  f"{emoji} {title}",
102
102
  DesignSystem.SECTION_SEP * w,
103
- "" # Blank line after separator
103
+ "", # Blank line after separator
104
104
  ]
105
105
  return lines
106
106