@atlascrew/apparatus 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/bin/apparatus.mjs +2 -0
  2. package/certs/server.crt +17 -0
  3. package/certs/server.key +28 -0
  4. package/dist/ai/client.js +104 -0
  5. package/dist/ai/client.js.map +1 -0
  6. package/dist/ai/personas.js +104 -0
  7. package/dist/ai/personas.js.map +1 -0
  8. package/dist/ai/redteam.js +1404 -0
  9. package/dist/ai/redteam.js.map +1 -0
  10. package/dist/ai/report-store.js +309 -0
  11. package/dist/ai/report-store.js.map +1 -0
  12. package/dist/app.js +525 -0
  13. package/dist/app.js.map +1 -0
  14. package/dist/attack-sim.js +69 -0
  15. package/dist/attack-sim.js.map +1 -0
  16. package/dist/attacker-tracker.js +276 -0
  17. package/dist/attacker-tracker.js.map +1 -0
  18. package/dist/blackhole.js +95 -0
  19. package/dist/blackhole.js.map +1 -0
  20. package/dist/chaos.js +88 -0
  21. package/dist/chaos.js.map +1 -0
  22. package/dist/cluster.js +462 -0
  23. package/dist/cluster.js.map +1 -0
  24. package/dist/config.js +61 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/deception.js +205 -0
  27. package/dist/deception.js.map +1 -0
  28. package/dist/demo-mode.js +109 -0
  29. package/dist/demo-mode.js.map +1 -0
  30. package/dist/dist-dashboard/assets/index-BsMhEnGu.js +648 -0
  31. package/dist/dist-dashboard/assets/index-CNOkYC_Q.css +10 -0
  32. package/dist/dist-dashboard/assets/index-CW2grvPC.js +648 -0
  33. package/dist/dist-dashboard/assets/logo/apparatus-favicon.svg +15 -0
  34. package/dist/dist-dashboard/assets/logo/apparatus-icon-dark.svg +24 -0
  35. package/dist/dist-dashboard/assets/logo/apparatus-icon-light.svg +24 -0
  36. package/dist/dist-dashboard/assets/logo/apparatus-logo-512.png +0 -0
  37. package/dist/dist-dashboard/assets/logo/apparatus-logo-dark.svg +18 -0
  38. package/dist/dist-dashboard/assets/logo/apparatus-logo.svg +17 -0
  39. package/dist/dist-dashboard/assets/logo/apple-touch-icon.png +0 -0
  40. package/dist/dist-dashboard/assets/logo/favicon-192.png +0 -0
  41. package/dist/dist-dashboard/assets/logo/favicon-32.png +0 -0
  42. package/dist/dist-dashboard/assets/logo/favicon.ico +0 -0
  43. package/dist/dist-dashboard/assets/logo/icon-192.png +0 -0
  44. package/dist/dist-dashboard/assets/logo/icon-512.png +0 -0
  45. package/dist/dist-dashboard/assets/logo/icon-light-512.png +0 -0
  46. package/dist/dist-dashboard/assets/react-vendor-DpRMSntD.js +1 -0
  47. package/dist/dist-dashboard/assets/router-DSc5pRwN.js +59 -0
  48. package/dist/dist-dashboard/docs-index.json +1577 -0
  49. package/dist/dist-dashboard/index.html +21 -0
  50. package/dist/dlp.js +40 -0
  51. package/dist/dlp.js.map +1 -0
  52. package/dist/drills.js +770 -0
  53. package/dist/drills.js.map +1 -0
  54. package/dist/echoHandler.js +113 -0
  55. package/dist/echoHandler.js.map +1 -0
  56. package/dist/escape/index.js +225 -0
  57. package/dist/escape/index.js.map +1 -0
  58. package/dist/escape/methods/dns.js +74 -0
  59. package/dist/escape/methods/dns.js.map +1 -0
  60. package/dist/escape/methods/http.js +81 -0
  61. package/dist/escape/methods/http.js.map +1 -0
  62. package/dist/escape/methods/icmp.js +36 -0
  63. package/dist/escape/methods/icmp.js.map +1 -0
  64. package/dist/escape/methods/tcp.js +38 -0
  65. package/dist/escape/methods/tcp.js.map +1 -0
  66. package/dist/escape/methods/udp.js +27 -0
  67. package/dist/escape/methods/udp.js.map +1 -0
  68. package/dist/escape/methods/websocket.js +37 -0
  69. package/dist/escape/methods/websocket.js.map +1 -0
  70. package/dist/forensics.js +111 -0
  71. package/dist/forensics.js.map +1 -0
  72. package/dist/generator.js +67 -0
  73. package/dist/generator.js.map +1 -0
  74. package/dist/ghosting.js +414 -0
  75. package/dist/ghosting.js.map +1 -0
  76. package/dist/graphql.js +44 -0
  77. package/dist/graphql.js.map +1 -0
  78. package/dist/history.js +40 -0
  79. package/dist/history.js.map +1 -0
  80. package/dist/imposter/creds.js +16 -0
  81. package/dist/imposter/creds.js.map +1 -0
  82. package/dist/imposter/index.js +44 -0
  83. package/dist/imposter/index.js.map +1 -0
  84. package/dist/imposter/providers/aws.js +103 -0
  85. package/dist/imposter/providers/aws.js.map +1 -0
  86. package/dist/imposter/providers/gcp.js +26 -0
  87. package/dist/imposter/providers/gcp.js.map +1 -0
  88. package/dist/index.js +53 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/infra-debug.js +68 -0
  91. package/dist/infra-debug.js.map +1 -0
  92. package/dist/jwt-debug.js +272 -0
  93. package/dist/jwt-debug.js.map +1 -0
  94. package/dist/kv.js +22 -0
  95. package/dist/kv.js.map +1 -0
  96. package/dist/lib/generators.js +43 -0
  97. package/dist/lib/generators.js.map +1 -0
  98. package/dist/lib/json.js +26 -0
  99. package/dist/lib/json.js.map +1 -0
  100. package/dist/logger.js +9 -0
  101. package/dist/logger.js.map +1 -0
  102. package/dist/metrics.js +20 -0
  103. package/dist/metrics.js.map +1 -0
  104. package/dist/mtd.js +30 -0
  105. package/dist/mtd.js.map +1 -0
  106. package/dist/oidc.js +69 -0
  107. package/dist/oidc.js.map +1 -0
  108. package/dist/persistence/cluster-state.js +47 -0
  109. package/dist/persistence/cluster-state.js.map +1 -0
  110. package/dist/persistence/deception-history.js +65 -0
  111. package/dist/persistence/deception-history.js.map +1 -0
  112. package/dist/persistence/drill-runs.js +138 -0
  113. package/dist/persistence/drill-runs.js.map +1 -0
  114. package/dist/persistence/request-history.js +41 -0
  115. package/dist/persistence/request-history.js.map +1 -0
  116. package/dist/persistence/scenario-catalog.js +73 -0
  117. package/dist/persistence/scenario-catalog.js.map +1 -0
  118. package/dist/persistence/status.js +51 -0
  119. package/dist/persistence/status.js.map +1 -0
  120. package/dist/persistence/tarpit-state.js +47 -0
  121. package/dist/persistence/tarpit-state.js.map +1 -0
  122. package/dist/persistence/webhook-store.js +69 -0
  123. package/dist/persistence/webhook-store.js.map +1 -0
  124. package/dist/proxy.js +28 -0
  125. package/dist/proxy.js.map +1 -0
  126. package/dist/ratelimit.js +32 -0
  127. package/dist/ratelimit.js.map +1 -0
  128. package/dist/redteam.js +442 -0
  129. package/dist/redteam.js.map +1 -0
  130. package/dist/scenarios.js +229 -0
  131. package/dist/scenarios.js.map +1 -0
  132. package/dist/scripting.js +30 -0
  133. package/dist/scripting.js.map +1 -0
  134. package/dist/self-healing.js +42 -0
  135. package/dist/self-healing.js.map +1 -0
  136. package/dist/sentinel.js +50 -0
  137. package/dist/sentinel.js.map +1 -0
  138. package/dist/server-bad-ssl.js +47 -0
  139. package/dist/server-bad-ssl.js.map +1 -0
  140. package/dist/server-grpc.js +66 -0
  141. package/dist/server-grpc.js.map +1 -0
  142. package/dist/server-http1.js +5 -0
  143. package/dist/server-http1.js.map +1 -0
  144. package/dist/server-http2.js +27 -0
  145. package/dist/server-http2.js.map +1 -0
  146. package/dist/server-icap.js +46 -0
  147. package/dist/server-icap.js.map +1 -0
  148. package/dist/server-l4.js +30 -0
  149. package/dist/server-l4.js.map +1 -0
  150. package/dist/server-mqtt.js +29 -0
  151. package/dist/server-mqtt.js.map +1 -0
  152. package/dist/server-protocols.js +18 -0
  153. package/dist/server-protocols.js.map +1 -0
  154. package/dist/server-redis.js +112 -0
  155. package/dist/server-redis.js.map +1 -0
  156. package/dist/server-smtp.js +66 -0
  157. package/dist/server-smtp.js.map +1 -0
  158. package/dist/server-syslog.js +23 -0
  159. package/dist/server-syslog.js.map +1 -0
  160. package/dist/server-ws.js +18 -0
  161. package/dist/server-ws.js.map +1 -0
  162. package/dist/sidecar/chaos/engine.js +41 -0
  163. package/dist/sidecar/chaos/engine.js.map +1 -0
  164. package/dist/sidecar/index.js +98 -0
  165. package/dist/sidecar/index.js.map +1 -0
  166. package/dist/simulator/dependency-graph.js +102 -0
  167. package/dist/simulator/dependency-graph.js.map +1 -0
  168. package/dist/simulator/supply-chain.js +67 -0
  169. package/dist/simulator/supply-chain.js.map +1 -0
  170. package/dist/sink.js +24 -0
  171. package/dist/sink.js.map +1 -0
  172. package/dist/sse-broadcast.js +105 -0
  173. package/dist/sse-broadcast.js.map +1 -0
  174. package/dist/swagger.js +309 -0
  175. package/dist/swagger.js.map +1 -0
  176. package/dist/sysinfo.js +36 -0
  177. package/dist/sysinfo.js.map +1 -0
  178. package/dist/tarpit.js +126 -0
  179. package/dist/tarpit.js.map +1 -0
  180. package/dist/tool-executor.js +315 -0
  181. package/dist/tool-executor.js.map +1 -0
  182. package/dist/tui/api-client.js +341 -0
  183. package/dist/tui/api-client.js.map +1 -0
  184. package/dist/tui/core/action-handler.js +302 -0
  185. package/dist/tui/core/action-handler.js.map +1 -0
  186. package/dist/tui/core/index.js +18 -0
  187. package/dist/tui/core/index.js.map +1 -0
  188. package/dist/tui/core/keyboard.js +329 -0
  189. package/dist/tui/core/keyboard.js.map +1 -0
  190. package/dist/tui/core/modal.js +397 -0
  191. package/dist/tui/core/modal.js.map +1 -0
  192. package/dist/tui/core/screen-manager.js +262 -0
  193. package/dist/tui/core/screen-manager.js.map +1 -0
  194. package/dist/tui/core/store.js +254 -0
  195. package/dist/tui/core/store.js.map +1 -0
  196. package/dist/tui/core/widget.js +167 -0
  197. package/dist/tui/core/widget.js.map +1 -0
  198. package/dist/tui/dashboard.js +649 -0
  199. package/dist/tui/dashboard.js.map +1 -0
  200. package/dist/tui/index.js +118 -0
  201. package/dist/tui/index.js.map +1 -0
  202. package/dist/tui/modals/add-rule-modal.js +190 -0
  203. package/dist/tui/modals/add-rule-modal.js.map +1 -0
  204. package/dist/tui/modals/dlp-output-modal.js +102 -0
  205. package/dist/tui/modals/dlp-output-modal.js.map +1 -0
  206. package/dist/tui/modals/dns-form-modal.js +26 -0
  207. package/dist/tui/modals/dns-form-modal.js.map +1 -0
  208. package/dist/tui/modals/ghost-config-modal.js +35 -0
  209. package/dist/tui/modals/ghost-config-modal.js.map +1 -0
  210. package/dist/tui/modals/har-results-modal.js +41 -0
  211. package/dist/tui/modals/har-results-modal.js.map +1 -0
  212. package/dist/tui/modals/index.js +15 -0
  213. package/dist/tui/modals/index.js.map +1 -0
  214. package/dist/tui/modals/jwt-decode-modal.js +45 -0
  215. package/dist/tui/modals/jwt-decode-modal.js.map +1 -0
  216. package/dist/tui/modals/jwt-mint-modal.js +70 -0
  217. package/dist/tui/modals/jwt-mint-modal.js.map +1 -0
  218. package/dist/tui/modals/ping-form-modal.js +19 -0
  219. package/dist/tui/modals/ping-form-modal.js.map +1 -0
  220. package/dist/tui/modals/redteam-results-modal.js +43 -0
  221. package/dist/tui/modals/redteam-results-modal.js.map +1 -0
  222. package/dist/tui/modals/scan-form-modal.js +26 -0
  223. package/dist/tui/modals/scan-form-modal.js.map +1 -0
  224. package/dist/tui/screens/defense-screen.js +281 -0
  225. package/dist/tui/screens/defense-screen.js.map +1 -0
  226. package/dist/tui/screens/forensics-screen.js +81 -0
  227. package/dist/tui/screens/forensics-screen.js.map +1 -0
  228. package/dist/tui/screens/index.js +140 -0
  229. package/dist/tui/screens/index.js.map +1 -0
  230. package/dist/tui/screens/system-screen.js +81 -0
  231. package/dist/tui/screens/system-screen.js.map +1 -0
  232. package/dist/tui/screens/testing-screen.js +429 -0
  233. package/dist/tui/screens/testing-screen.js.map +1 -0
  234. package/dist/tui/screens/traffic-screen.js +76 -0
  235. package/dist/tui/screens/traffic-screen.js.map +1 -0
  236. package/dist/tui/sse-client.js +130 -0
  237. package/dist/tui/sse-client.js.map +1 -0
  238. package/dist/tui/state/metrics-buffer.js +195 -0
  239. package/dist/tui/state/metrics-buffer.js.map +1 -0
  240. package/dist/tui/state/metrics-buffer.test.js +102 -0
  241. package/dist/tui/state/metrics-buffer.test.js.map +1 -0
  242. package/dist/tui/theme.js +136 -0
  243. package/dist/tui/theme.js.map +1 -0
  244. package/dist/tui/types.js +6 -0
  245. package/dist/tui/types.js.map +1 -0
  246. package/dist/tui/widgets/chaos-widget.js +152 -0
  247. package/dist/tui/widgets/chaos-widget.js.map +1 -0
  248. package/dist/tui/widgets/cluster-widget.js +156 -0
  249. package/dist/tui/widgets/cluster-widget.js.map +1 -0
  250. package/dist/tui/widgets/dlp-widget.js +161 -0
  251. package/dist/tui/widgets/dlp-widget.js.map +1 -0
  252. package/dist/tui/widgets/ghost-widget.js +169 -0
  253. package/dist/tui/widgets/ghost-widget.js.map +1 -0
  254. package/dist/tui/widgets/har-widget.js +173 -0
  255. package/dist/tui/widgets/har-widget.js.map +1 -0
  256. package/dist/tui/widgets/index.js +122 -0
  257. package/dist/tui/widgets/index.js.map +1 -0
  258. package/dist/tui/widgets/jwt-widget.js +177 -0
  259. package/dist/tui/widgets/jwt-widget.js.map +1 -0
  260. package/dist/tui/widgets/kv-widget.js +261 -0
  261. package/dist/tui/widgets/kv-widget.js.map +1 -0
  262. package/dist/tui/widgets/mtd-widget.js +181 -0
  263. package/dist/tui/widgets/mtd-widget.js.map +1 -0
  264. package/dist/tui/widgets/netdiag-widget.js +155 -0
  265. package/dist/tui/widgets/netdiag-widget.js.map +1 -0
  266. package/dist/tui/widgets/oidc-widget.js +162 -0
  267. package/dist/tui/widgets/oidc-widget.js.map +1 -0
  268. package/dist/tui/widgets/pcap-widget.js +239 -0
  269. package/dist/tui/widgets/pcap-widget.js.map +1 -0
  270. package/dist/tui/widgets/redteam-widget.js +155 -0
  271. package/dist/tui/widgets/redteam-widget.js.map +1 -0
  272. package/dist/tui/widgets/rps-gauge-widget.js +124 -0
  273. package/dist/tui/widgets/rps-gauge-widget.js.map +1 -0
  274. package/dist/tui/widgets/sentinel-widget.js +171 -0
  275. package/dist/tui/widgets/sentinel-widget.js.map +1 -0
  276. package/dist/tui/widgets/sparklines-widget.js +127 -0
  277. package/dist/tui/widgets/sparklines-widget.js.map +1 -0
  278. package/dist/tui/widgets/sysinfo-widget.js +197 -0
  279. package/dist/tui/widgets/sysinfo-widget.js.map +1 -0
  280. package/dist/tui/widgets/traffic-chart-widget.js +170 -0
  281. package/dist/tui/widgets/traffic-chart-widget.js.map +1 -0
  282. package/dist/tui/widgets/webhook-widget.js +259 -0
  283. package/dist/tui/widgets/webhook-widget.js.map +1 -0
  284. package/dist/utils/ip.js +18 -0
  285. package/dist/utils/ip.js.map +1 -0
  286. package/dist/victim/index.js +71 -0
  287. package/dist/victim/index.js.map +1 -0
  288. package/dist/webhook.js +88 -0
  289. package/dist/webhook.js.map +1 -0
  290. package/package.json +90 -0
  291. package/proto/echo.proto +19 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Screen Registry
3
+ *
4
+ * Defines all screens for the TUI dashboard with their
5
+ * widget configurations and navigation shortcuts.
6
+ */
7
+ import { createTrafficScreen } from './traffic-screen.js';
8
+ import { createSystemScreen } from './system-screen.js';
9
+ import { createForensicsScreen } from './forensics-screen.js';
10
+ // Re-export screens
11
+ export { createTrafficScreen } from './traffic-screen.js';
12
+ export { createTestingScreen } from './testing-screen.js';
13
+ export { createSystemScreen } from './system-screen.js';
14
+ export { createForensicsScreen } from './forensics-screen.js';
15
+ /**
16
+ * Screen ID constants
17
+ */
18
+ export const SCREEN_IDS = {
19
+ MAIN: 'main',
20
+ TRAFFIC: 'traffic',
21
+ TESTING: 'testing',
22
+ DEFENSE: 'defense',
23
+ SYSTEM: 'system',
24
+ FORENSICS: 'forensics',
25
+ };
26
+ /**
27
+ * All available screens with metadata
28
+ */
29
+ export const SCREENS = [
30
+ {
31
+ id: SCREEN_IDS.MAIN,
32
+ name: 'Monitor',
33
+ shortcut: '1',
34
+ description: 'Main monitoring dashboard with health, requests, and alerts',
35
+ },
36
+ {
37
+ id: SCREEN_IDS.TRAFFIC,
38
+ name: 'Traffic',
39
+ shortcut: '2',
40
+ description: 'Traffic visualization with RPS, sparklines, and charts',
41
+ },
42
+ {
43
+ id: SCREEN_IDS.TESTING,
44
+ name: 'Testing',
45
+ shortcut: '3',
46
+ description: 'Red Team, Chaos Engineering, and Network Diagnostics',
47
+ },
48
+ {
49
+ id: SCREEN_IDS.DEFENSE,
50
+ name: 'Defense',
51
+ shortcut: '4',
52
+ description: 'Active Shield, MTD, and DLP configuration',
53
+ },
54
+ {
55
+ id: SCREEN_IDS.SYSTEM,
56
+ name: 'System',
57
+ shortcut: '5',
58
+ description: 'Cluster topology, System info, KV Store, and Webhooks',
59
+ },
60
+ {
61
+ id: SCREEN_IDS.FORENSICS,
62
+ name: 'Forensics',
63
+ shortcut: '6',
64
+ description: 'PCAP capture, HAR replay, JWT tools, and OIDC configuration',
65
+ },
66
+ ];
67
+ /**
68
+ * Screen registry
69
+ */
70
+ class ScreenRegistry {
71
+ factories = new Map();
72
+ /**
73
+ * Register a screen factory
74
+ */
75
+ register(id, factory) {
76
+ this.factories.set(id, factory);
77
+ }
78
+ /**
79
+ * Create a screen by ID
80
+ */
81
+ create(id) {
82
+ const factory = this.factories.get(id);
83
+ return factory ? factory() : null;
84
+ }
85
+ /**
86
+ * Get all registered screen IDs
87
+ */
88
+ getRegisteredIds() {
89
+ return Array.from(this.factories.keys());
90
+ }
91
+ /**
92
+ * Check if a screen is registered
93
+ */
94
+ has(id) {
95
+ return this.factories.has(id);
96
+ }
97
+ /**
98
+ * Get screen metadata by ID
99
+ */
100
+ getMeta(id) {
101
+ return SCREENS.find((s) => s.id === id);
102
+ }
103
+ }
104
+ /**
105
+ * Global screen registry instance
106
+ */
107
+ export const screenRegistry = new ScreenRegistry();
108
+ /**
109
+ * Initialize all screen factories
110
+ * This is called during dashboard startup to register all screens
111
+ */
112
+ export function initializeScreens() {
113
+ // Traffic Screen (Workstream 1)
114
+ screenRegistry.register(SCREEN_IDS.TRAFFIC, createTrafficScreen);
115
+ // Testing Screen (Workstream 2)
116
+ // Note: Testing screen is not a ScreenDefinition, it's a custom screen class
117
+ // It will be initialized separately in the main dashboard
118
+ // System Screen (Workstream 4)
119
+ screenRegistry.register(SCREEN_IDS.SYSTEM, createSystemScreen);
120
+ // Forensics Screen (Workstream 5)
121
+ screenRegistry.register(SCREEN_IDS.FORENSICS, createForensicsScreen);
122
+ // Additional screens will be registered here as they are implemented
123
+ }
124
+ /**
125
+ * Get screen names for tab bar
126
+ */
127
+ export function getScreenNames() {
128
+ return SCREENS.map((s) => s.name);
129
+ }
130
+ /**
131
+ * Get screen shortcuts for keyboard binding
132
+ */
133
+ export function getScreenShortcuts() {
134
+ const shortcuts = {};
135
+ for (const screen of SCREENS) {
136
+ shortcuts[screen.shortcut] = screen.id;
137
+ }
138
+ return shortcuts;
139
+ }
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tui/screens/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,oBAAoB;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;CACd,CAAC;AAcX;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC;QACE,EAAE,EAAE,UAAU,CAAC,IAAI;QACnB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,6DAA6D;KAC3E;IACD;QACE,EAAE,EAAE,UAAU,CAAC,OAAO;QACtB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,wDAAwD;KACtE;IACD;QACE,EAAE,EAAE,UAAU,CAAC,OAAO;QACtB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,sDAAsD;KACpE;IACD;QACE,EAAE,EAAE,UAAU,CAAC,OAAO;QACtB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,2CAA2C;KACzD;IACD;QACE,EAAE,EAAE,UAAU,CAAC,MAAM;QACrB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,uDAAuD;KACrE;IACD;QACE,EAAE,EAAE,UAAU,CAAC,SAAS;QACxB,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,6DAA6D;KAC3E;CACF,CAAC;AAOF;;GAEG;AACH,MAAM,cAAc;IACV,SAAS,GAAiC,IAAI,GAAG,EAAE,CAAC;IAE5D;;OAEG;IACH,QAAQ,CAAC,EAAY,EAAE,OAAsB;QAC3C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAY;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,EAAY;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,EAAY;QAClB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,gCAAgC;IAChC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAEjE,gCAAgC;IAChC,6EAA6E;IAC7E,0DAA0D;IAE1D,+BAA+B;IAC/B,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAE/D,kCAAkC;IAClC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAErE,qEAAqE;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,SAAS,GAA6B,EAAE,CAAC;IAC/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * System Screen
3
+ *
4
+ * Combines cluster topology, system info, KV store, and webhook inspector
5
+ * widgets in a grid layout.
6
+ */
7
+ import { createClusterWidget } from '../widgets/cluster-widget.js';
8
+ import { createSysInfoWidget } from '../widgets/sysinfo-widget.js';
9
+ import { createKVWidget } from '../widgets/kv-widget.js';
10
+ import { createWebhookWidget } from '../widgets/webhook-widget.js';
11
+ /**
12
+ * Create System Screen
13
+ *
14
+ * Layout (12x12 grid):
15
+ * ┌─────────────────────────────────────┐
16
+ * │ Cluster (6 cols) │ SysInfo (6 cols) │
17
+ * │ │ │
18
+ * ├─────────────────────────────────────┤
19
+ * │ KV Store (6 cols)│ Webhooks (6 cols)│
20
+ * │ │ │
21
+ * └─────────────────────────────────────┘
22
+ */
23
+ export function createSystemScreen() {
24
+ // Create widget instances
25
+ const clusterWidget = createClusterWidget('cluster-topology', {
26
+ row: 1,
27
+ col: 0,
28
+ rowSpan: 6,
29
+ colSpan: 6,
30
+ label: 'Cluster Topology',
31
+ style: {
32
+ border: { fg: 'blue' },
33
+ label: { fg: 'white' },
34
+ },
35
+ });
36
+ const sysinfoWidget = createSysInfoWidget('system-info', {
37
+ row: 1,
38
+ col: 6,
39
+ rowSpan: 6,
40
+ colSpan: 6,
41
+ label: 'System Information',
42
+ style: {
43
+ border: { fg: 'cyan' },
44
+ label: { fg: 'white' },
45
+ },
46
+ });
47
+ const kvWidget = createKVWidget('kv-store', {
48
+ row: 7,
49
+ col: 0,
50
+ rowSpan: 5,
51
+ colSpan: 6,
52
+ label: 'KV Store',
53
+ style: {
54
+ border: { fg: 'green' },
55
+ label: { fg: 'white' },
56
+ },
57
+ });
58
+ const webhookWidget = createWebhookWidget('webhook-inspector', {
59
+ row: 7,
60
+ col: 6,
61
+ rowSpan: 5,
62
+ colSpan: 6,
63
+ label: 'Webhook Inspector',
64
+ style: {
65
+ border: { fg: 'yellow' },
66
+ label: { fg: 'white' },
67
+ },
68
+ });
69
+ return {
70
+ id: 'system',
71
+ name: 'System',
72
+ shortcut: '5',
73
+ widgets: [
74
+ { widget: clusterWidget, config: clusterWidget.config },
75
+ { widget: sysinfoWidget, config: sysinfoWidget.config },
76
+ { widget: kvWidget, config: kvWidget.config },
77
+ { widget: webhookWidget, config: webhookWidget.config },
78
+ ],
79
+ };
80
+ }
81
+ //# sourceMappingURL=system-screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-screen.js","sourceRoot":"","sources":["../../../src/tui/screens/system-screen.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB;IAChC,0BAA0B;IAC1B,MAAM,aAAa,GAAG,mBAAmB,CAAC,kBAAkB,EAAE;QAC5D,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,kBAAkB;QACzB,KAAK,EAAE;YACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;YACtB,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;SACvB;KACF,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,mBAAmB,CAAC,aAAa,EAAE;QACvD,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,oBAAoB;QAC3B,KAAK,EAAE;YACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;YACtB,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;SACvB;KACF,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,EAAE;QAC1C,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE;YACL,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;YACvB,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;SACvB;KACF,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,mBAAmB,CAAC,mBAAmB,EAAE;QAC7D,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,mBAAmB;QAC1B,KAAK,EAAE;YACL,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE;YACxB,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;SACvB;KACF,CAAC,CAAC;IAEH,OAAO;QACL,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE;YACP,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE;YACvD,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE;YACvD,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;YAC7C,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE;SACxD;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,429 @@
1
+ /**
2
+ * Testing Screen
3
+ * Combines all testing and control widgets in a grid layout
4
+ */
5
+ import blessed from 'blessed';
6
+ import { RedTeamWidget } from '../widgets/redteam-widget.js';
7
+ import { ChaosWidget } from '../widgets/chaos-widget.js';
8
+ import { GhostWidget } from '../widgets/ghost-widget.js';
9
+ import { NetDiagWidget } from '../widgets/netdiag-widget.js';
10
+ import { showRedTeamResultsModal, showDnsFormModal, showPingFormModal, showScanFormModal, showGhostConfigModal, } from '../modals/index.js';
11
+ export class TestingScreen {
12
+ screen;
13
+ store;
14
+ modal;
15
+ actionHandler;
16
+ client;
17
+ container;
18
+ grid;
19
+ widgets;
20
+ constructor(options) {
21
+ this.screen = options.screen;
22
+ this.store = options.store;
23
+ this.modal = options.modal;
24
+ this.actionHandler = options.actionHandler;
25
+ this.client = options.client;
26
+ // Create container
27
+ this.container = blessed.box({
28
+ parent: this.screen,
29
+ top: 0,
30
+ left: 0,
31
+ width: '100%',
32
+ height: '100%',
33
+ hidden: true,
34
+ });
35
+ // Create grid layout (2x2)
36
+ this.grid = blessed.layout({
37
+ parent: this.container,
38
+ top: 0,
39
+ left: 0,
40
+ width: '100%',
41
+ height: '100%',
42
+ layout: 'grid',
43
+ });
44
+ // Create widgets
45
+ this.widgets = {
46
+ redteam: new RedTeamWidget('redteam', {
47
+ row: 0,
48
+ col: 0,
49
+ rowSpan: 1,
50
+ colSpan: 1,
51
+ label: 'Red Team Scanner',
52
+ }),
53
+ chaos: new ChaosWidget('chaos', {
54
+ row: 0,
55
+ col: 1,
56
+ rowSpan: 1,
57
+ colSpan: 1,
58
+ label: 'Chaos Engineering',
59
+ }),
60
+ ghost: new GhostWidget('ghost', {
61
+ row: 1,
62
+ col: 0,
63
+ rowSpan: 1,
64
+ colSpan: 1,
65
+ label: 'Ghost Traffic',
66
+ }),
67
+ netdiag: new NetDiagWidget('netdiag', {
68
+ row: 1,
69
+ col: 1,
70
+ rowSpan: 1,
71
+ colSpan: 1,
72
+ label: 'Network Diagnostics',
73
+ }),
74
+ };
75
+ // Mount widgets in grid
76
+ this.grid.append(this.widgets.redteam.element);
77
+ this.grid.append(this.widgets.chaos.element);
78
+ this.grid.append(this.widgets.ghost.element);
79
+ this.grid.append(this.widgets.netdiag.element);
80
+ // Mount widgets to store
81
+ this.widgets.redteam.mount(this.screen, this.store);
82
+ this.widgets.chaos.mount(this.screen, this.store);
83
+ this.widgets.ghost.mount(this.screen, this.store);
84
+ this.widgets.netdiag.mount(this.screen, this.store);
85
+ // Set up event handlers
86
+ this.setupEventHandlers();
87
+ // Set up keyboard bindings
88
+ this.setupKeyBindings();
89
+ }
90
+ setupEventHandlers() {
91
+ // Red Team events
92
+ this.store.on('scan:start', () => this.handleScanStart());
93
+ this.store.on('results:view', () => this.handleResultsView());
94
+ // Chaos events
95
+ this.store.on('chaos:cpu', () => this.handleChaosCpu());
96
+ this.store.on('chaos:memory', () => this.handleChaosMemory());
97
+ this.store.on('chaos:crash', () => this.handleChaosCrash());
98
+ this.store.on('chaos:clear', () => this.handleChaosClear());
99
+ // Ghost events
100
+ this.store.on('ghost:start', () => this.handleGhostStart());
101
+ this.store.on('ghost:stop', () => this.handleGhostStop());
102
+ this.store.on('ghost:setTarget', () => this.handleGhostSetTarget());
103
+ this.store.on('ghost:setDelay', () => this.handleGhostSetDelay());
104
+ // Network diagnostics events
105
+ this.store.on('netdiag:dns', () => this.handleDnsLookup());
106
+ this.store.on('netdiag:ping', () => this.handleTcpPing());
107
+ }
108
+ setupKeyBindings() {
109
+ // Global screen keys
110
+ this.screen.key(['escape', 'q'], () => {
111
+ this.hide();
112
+ });
113
+ // Focus navigation
114
+ this.screen.key(['tab'], () => {
115
+ this.screen.focusNext();
116
+ });
117
+ this.screen.key(['S-tab'], () => {
118
+ this.screen.focusPrevious();
119
+ });
120
+ }
121
+ // Red Team handlers
122
+ handleScanStart() {
123
+ showScanFormModal(this.modal, async (target, path) => {
124
+ this.widgets.redteam.setScanning(true);
125
+ try {
126
+ const result = await this.client.runRedTeamScan(target, path);
127
+ this.widgets.redteam.setLastScan({
128
+ target,
129
+ total: result.summary?.total ?? result.total,
130
+ blocked: result.summary?.blocked ?? result.blocked,
131
+ passed: result.summary?.passed ?? result.passed,
132
+ });
133
+ // Store result for viewing
134
+ this.widgets.redteam.lastFullResult = result;
135
+ }
136
+ catch (err) {
137
+ this.modal.showResult({
138
+ title: 'Error',
139
+ content: `Scan failed: ${err instanceof Error ? err.message : String(err)}`,
140
+ type: 'error',
141
+ });
142
+ this.widgets.redteam.setScanning(false);
143
+ }
144
+ });
145
+ }
146
+ handleResultsView() {
147
+ const result = this.widgets.redteam.lastFullResult;
148
+ if (result) {
149
+ showRedTeamResultsModal(this.modal, result);
150
+ }
151
+ }
152
+ // Chaos handlers
153
+ handleChaosCpu() {
154
+ this.modal.showConfirm({
155
+ title: 'Chaos: CPU Spike',
156
+ message: 'Trigger CPU spike for 5 seconds?',
157
+ danger: true,
158
+ }, async () => {
159
+ try {
160
+ this.widgets.chaos.setCpuActive(true);
161
+ await this.client.triggerCpuSpike(5000);
162
+ setTimeout(() => {
163
+ this.widgets.chaos.setCpuActive(false);
164
+ }, 5000);
165
+ this.modal.showResult({
166
+ title: 'Success',
167
+ content: 'CPU spike triggered for 5 seconds',
168
+ type: 'success',
169
+ });
170
+ }
171
+ catch (err) {
172
+ this.modal.showResult({
173
+ title: 'Error',
174
+ content: `Failed to trigger CPU spike: ${err instanceof Error ? err.message : String(err)}`,
175
+ type: 'error',
176
+ });
177
+ this.widgets.chaos.setCpuActive(false);
178
+ }
179
+ });
180
+ }
181
+ handleChaosMemory() {
182
+ this.modal.showConfirm({
183
+ title: 'Chaos: Memory Spike',
184
+ message: 'Allocate 100MB of memory?',
185
+ danger: true,
186
+ }, async () => {
187
+ try {
188
+ await this.client.triggerMemorySpike(100);
189
+ this.widgets.chaos.setMemoryAllocated(100);
190
+ this.modal.showResult({
191
+ title: 'Success',
192
+ content: 'Allocated 100MB of memory',
193
+ type: 'success',
194
+ });
195
+ }
196
+ catch (err) {
197
+ this.modal.showResult({
198
+ title: 'Error',
199
+ content: `Failed to allocate memory: ${err instanceof Error ? err.message : String(err)}`,
200
+ type: 'error',
201
+ });
202
+ }
203
+ });
204
+ }
205
+ handleChaosCrash() {
206
+ this.modal.showConfirm({
207
+ title: 'Chaos: Crash Server',
208
+ message: 'DANGER: This will crash the server! Continue?',
209
+ danger: true,
210
+ confirmLabel: 'CRASH',
211
+ }, async () => {
212
+ try {
213
+ await this.client.triggerCrash();
214
+ this.modal.showResult({
215
+ title: 'Server Crashed',
216
+ content: 'Server crash triggered. Reconnection may be required.',
217
+ type: 'warning',
218
+ });
219
+ }
220
+ catch (err) {
221
+ // Expected - server will disconnect
222
+ this.modal.showResult({
223
+ title: 'Server Crashed',
224
+ content: 'Server has been terminated. Reconnection required.',
225
+ type: 'warning',
226
+ });
227
+ }
228
+ });
229
+ }
230
+ handleChaosClear() {
231
+ this.modal.showConfirm({
232
+ title: 'Clear Memory',
233
+ message: 'Clear all allocated memory?',
234
+ }, async () => {
235
+ try {
236
+ await this.client.clearMemory();
237
+ this.widgets.chaos.setMemoryAllocated(0);
238
+ this.modal.showResult({
239
+ title: 'Success',
240
+ content: 'Memory cleared',
241
+ type: 'success',
242
+ });
243
+ }
244
+ catch (err) {
245
+ this.modal.showResult({
246
+ title: 'Error',
247
+ content: `Failed to clear memory: ${err instanceof Error ? err.message : String(err)}`,
248
+ type: 'error',
249
+ });
250
+ }
251
+ });
252
+ }
253
+ // Ghost traffic handlers
254
+ handleGhostStart() {
255
+ const currentTarget = this.widgets.ghost.state.target;
256
+ const currentDelay = this.widgets.ghost.state.delay;
257
+ if (!currentTarget) {
258
+ this.modal.showResult({
259
+ title: 'Error',
260
+ content: 'Please set a target URL first (press T)',
261
+ type: 'error',
262
+ });
263
+ return;
264
+ }
265
+ this.modal.showConfirm({
266
+ title: 'Start Ghost Traffic',
267
+ message: `Start traffic to ${currentTarget} with ${currentDelay}ms delay?`,
268
+ }, async () => {
269
+ try {
270
+ await this.client.startGhostTraffic(currentTarget, currentDelay);
271
+ this.widgets.ghost.setActive(true, currentTarget);
272
+ this.modal.showResult({
273
+ title: 'Success',
274
+ content: 'Ghost traffic started',
275
+ type: 'success',
276
+ });
277
+ }
278
+ catch (err) {
279
+ this.modal.showResult({
280
+ title: 'Error',
281
+ content: `Failed to start ghost traffic: ${err instanceof Error ? err.message : String(err)}`,
282
+ type: 'error',
283
+ });
284
+ }
285
+ });
286
+ }
287
+ handleGhostStop() {
288
+ this.modal.showConfirm({
289
+ title: 'Stop Ghost Traffic',
290
+ message: 'Stop ghost traffic generation?',
291
+ }, async () => {
292
+ try {
293
+ await this.client.stopGhostTraffic();
294
+ this.widgets.ghost.setActive(false);
295
+ this.modal.showResult({
296
+ title: 'Success',
297
+ content: 'Ghost traffic stopped',
298
+ type: 'success',
299
+ });
300
+ }
301
+ catch (err) {
302
+ this.modal.showResult({
303
+ title: 'Error',
304
+ content: `Failed to stop ghost traffic: ${err instanceof Error ? err.message : String(err)}`,
305
+ type: 'error',
306
+ });
307
+ }
308
+ });
309
+ }
310
+ handleGhostSetTarget() {
311
+ const currentTarget = this.widgets.ghost.state.target || 'http://localhost:8080';
312
+ showGhostConfigModal(this.modal, 'target', currentTarget, (value) => {
313
+ this.widgets.ghost.setTarget(String(value));
314
+ this.modal.showResult({
315
+ title: 'Success',
316
+ content: `Target set to ${value}`,
317
+ type: 'success',
318
+ });
319
+ });
320
+ }
321
+ handleGhostSetDelay() {
322
+ const currentDelay = this.widgets.ghost.state.delay || 1000;
323
+ showGhostConfigModal(this.modal, 'delay', currentDelay, (value) => {
324
+ this.widgets.ghost.setDelay(Number(value));
325
+ this.modal.showResult({
326
+ title: 'Success',
327
+ content: `Delay set to ${value}ms`,
328
+ type: 'success',
329
+ });
330
+ });
331
+ }
332
+ // Network diagnostics handlers
333
+ handleDnsLookup() {
334
+ showDnsFormModal(this.modal, async (target, type) => {
335
+ this.modal.showLoading('Resolving DNS...');
336
+ try {
337
+ const result = await this.client.dnsLookup(target, type);
338
+ this.modal.close();
339
+ this.widgets.netdiag.setDnsResult({
340
+ target: result.target,
341
+ type: result.type,
342
+ records: result.records,
343
+ });
344
+ this.modal.showResult({
345
+ title: 'DNS Lookup Success',
346
+ content: `Found ${result.records.length} record(s) for ${target}`,
347
+ type: 'success',
348
+ });
349
+ }
350
+ catch (err) {
351
+ this.modal.close();
352
+ this.modal.showResult({
353
+ title: 'DNS Lookup Failed',
354
+ content: err instanceof Error ? err.message : String(err),
355
+ type: 'error',
356
+ });
357
+ }
358
+ });
359
+ }
360
+ handleTcpPing() {
361
+ showPingFormModal(this.modal, async (target) => {
362
+ this.modal.showLoading('Pinging...');
363
+ try {
364
+ const result = await this.client.tcpPing(target);
365
+ this.modal.close();
366
+ this.widgets.netdiag.setPingResult({
367
+ target: result.target,
368
+ reachable: result.reachable,
369
+ latencyMs: result.latencyMs,
370
+ error: result.error,
371
+ });
372
+ if (result.reachable) {
373
+ this.modal.showResult({
374
+ title: 'TCP Ping Success',
375
+ content: `${target} is reachable (${result.latencyMs}ms)`,
376
+ type: 'success',
377
+ });
378
+ }
379
+ else {
380
+ this.modal.showResult({
381
+ title: 'TCP Ping Failed',
382
+ content: result.error || 'Target is unreachable',
383
+ type: 'error',
384
+ });
385
+ }
386
+ }
387
+ catch (err) {
388
+ this.modal.close();
389
+ this.modal.showResult({
390
+ title: 'TCP Ping Failed',
391
+ content: err instanceof Error ? err.message : String(err),
392
+ type: 'error',
393
+ });
394
+ }
395
+ });
396
+ }
397
+ /**
398
+ * Show the testing screen
399
+ */
400
+ show() {
401
+ this.container.show();
402
+ this.widgets.redteam.element.focus();
403
+ this.screen.render();
404
+ }
405
+ /**
406
+ * Hide the testing screen
407
+ */
408
+ hide() {
409
+ this.container.hide();
410
+ this.screen.render();
411
+ }
412
+ /**
413
+ * Destroy the testing screen
414
+ */
415
+ destroy() {
416
+ this.widgets.redteam.destroy();
417
+ this.widgets.chaos.destroy();
418
+ this.widgets.ghost.destroy();
419
+ this.widgets.netdiag.destroy();
420
+ this.screen.remove(this.container);
421
+ }
422
+ }
423
+ /**
424
+ * Create a testing screen instance
425
+ */
426
+ export function createTestingScreen(options) {
427
+ return new TestingScreen(options);
428
+ }
429
+ //# sourceMappingURL=testing-screen.js.map