s3db.js 13.6.0 → 14.0.2

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 (193) hide show
  1. package/README.md +139 -43
  2. package/dist/s3db.cjs +72425 -38970
  3. package/dist/s3db.cjs.map +1 -1
  4. package/dist/s3db.es.js +72177 -38764
  5. package/dist/s3db.es.js.map +1 -1
  6. package/mcp/lib/base-handler.js +157 -0
  7. package/mcp/lib/handlers/connection-handler.js +280 -0
  8. package/mcp/lib/handlers/query-handler.js +533 -0
  9. package/mcp/lib/handlers/resource-handler.js +428 -0
  10. package/mcp/lib/tool-registry.js +336 -0
  11. package/mcp/lib/tools/connection-tools.js +161 -0
  12. package/mcp/lib/tools/query-tools.js +267 -0
  13. package/mcp/lib/tools/resource-tools.js +404 -0
  14. package/package.json +94 -49
  15. package/src/clients/memory-client.class.js +346 -191
  16. package/src/clients/memory-storage.class.js +300 -84
  17. package/src/clients/s3-client.class.js +7 -6
  18. package/src/concerns/geo-encoding.js +19 -2
  19. package/src/concerns/ip.js +59 -9
  20. package/src/concerns/money.js +8 -1
  21. package/src/concerns/password-hashing.js +49 -8
  22. package/src/concerns/plugin-storage.js +186 -18
  23. package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
  24. package/src/database.class.js +139 -29
  25. package/src/errors.js +332 -42
  26. package/src/plugins/api/auth/oidc-auth.js +66 -17
  27. package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
  28. package/src/plugins/api/auth/strategies/factory.class.js +63 -0
  29. package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
  30. package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
  31. package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
  32. package/src/plugins/api/concerns/failban-manager.js +106 -57
  33. package/src/plugins/api/concerns/opengraph-helper.js +116 -0
  34. package/src/plugins/api/concerns/route-context.js +601 -0
  35. package/src/plugins/api/concerns/state-machine.js +288 -0
  36. package/src/plugins/api/index.js +180 -41
  37. package/src/plugins/api/routes/auth-routes.js +198 -30
  38. package/src/plugins/api/routes/resource-routes.js +19 -4
  39. package/src/plugins/api/server/health-manager.class.js +163 -0
  40. package/src/plugins/api/server/middleware-chain.class.js +310 -0
  41. package/src/plugins/api/server/router.class.js +472 -0
  42. package/src/plugins/api/server.js +280 -1303
  43. package/src/plugins/api/utils/custom-routes.js +17 -5
  44. package/src/plugins/api/utils/guards.js +76 -17
  45. package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
  46. package/src/plugins/api/utils/openapi-generator.js +7 -6
  47. package/src/plugins/api/utils/template-engine.js +77 -3
  48. package/src/plugins/audit.plugin.js +30 -8
  49. package/src/plugins/backup.plugin.js +110 -14
  50. package/src/plugins/cache/cache.class.js +22 -5
  51. package/src/plugins/cache/filesystem-cache.class.js +116 -19
  52. package/src/plugins/cache/memory-cache.class.js +211 -57
  53. package/src/plugins/cache/multi-tier-cache.class.js +371 -0
  54. package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
  55. package/src/plugins/cache/redis-cache.class.js +552 -0
  56. package/src/plugins/cache/s3-cache.class.js +17 -8
  57. package/src/plugins/cache.plugin.js +176 -61
  58. package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
  59. package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
  60. package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
  61. package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
  62. package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
  63. package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
  64. package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
  65. package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
  66. package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
  67. package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
  68. package/src/plugins/cloud-inventory/index.js +29 -8
  69. package/src/plugins/cloud-inventory/registry.js +64 -42
  70. package/src/plugins/cloud-inventory.plugin.js +240 -138
  71. package/src/plugins/concerns/plugin-dependencies.js +54 -0
  72. package/src/plugins/concerns/resource-names.js +100 -0
  73. package/src/plugins/consumers/index.js +10 -2
  74. package/src/plugins/consumers/sqs-consumer.js +12 -2
  75. package/src/plugins/cookie-farm-suite.plugin.js +278 -0
  76. package/src/plugins/cookie-farm.errors.js +73 -0
  77. package/src/plugins/cookie-farm.plugin.js +869 -0
  78. package/src/plugins/costs.plugin.js +7 -1
  79. package/src/plugins/eventual-consistency/analytics.js +94 -19
  80. package/src/plugins/eventual-consistency/config.js +15 -7
  81. package/src/plugins/eventual-consistency/consolidation.js +29 -11
  82. package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
  83. package/src/plugins/eventual-consistency/helpers.js +39 -14
  84. package/src/plugins/eventual-consistency/install.js +21 -2
  85. package/src/plugins/eventual-consistency/utils.js +32 -10
  86. package/src/plugins/fulltext.plugin.js +38 -11
  87. package/src/plugins/geo.plugin.js +61 -9
  88. package/src/plugins/identity/concerns/config.js +61 -0
  89. package/src/plugins/identity/concerns/mfa-manager.js +15 -2
  90. package/src/plugins/identity/concerns/rate-limit.js +124 -0
  91. package/src/plugins/identity/concerns/resource-schemas.js +9 -1
  92. package/src/plugins/identity/concerns/token-generator.js +29 -4
  93. package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
  94. package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
  95. package/src/plugins/identity/drivers/index.js +18 -0
  96. package/src/plugins/identity/drivers/password-driver.js +122 -0
  97. package/src/plugins/identity/email-service.js +17 -2
  98. package/src/plugins/identity/index.js +413 -69
  99. package/src/plugins/identity/oauth2-server.js +413 -30
  100. package/src/plugins/identity/oidc-discovery.js +16 -8
  101. package/src/plugins/identity/rsa-keys.js +115 -35
  102. package/src/plugins/identity/server.js +166 -45
  103. package/src/plugins/identity/session-manager.js +53 -7
  104. package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
  105. package/src/plugins/identity/ui/routes.js +363 -255
  106. package/src/plugins/importer/index.js +153 -20
  107. package/src/plugins/index.js +9 -2
  108. package/src/plugins/kubernetes-inventory/index.js +6 -0
  109. package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
  110. package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
  111. package/src/plugins/kubernetes-inventory.plugin.js +980 -0
  112. package/src/plugins/metrics.plugin.js +64 -16
  113. package/src/plugins/ml/base-model.class.js +25 -15
  114. package/src/plugins/ml/regression-model.class.js +1 -1
  115. package/src/plugins/ml.errors.js +57 -25
  116. package/src/plugins/ml.plugin.js +28 -4
  117. package/src/plugins/namespace.js +210 -0
  118. package/src/plugins/plugin.class.js +180 -8
  119. package/src/plugins/puppeteer/console-monitor.js +729 -0
  120. package/src/plugins/puppeteer/cookie-manager.js +492 -0
  121. package/src/plugins/puppeteer/network-monitor.js +816 -0
  122. package/src/plugins/puppeteer/performance-manager.js +746 -0
  123. package/src/plugins/puppeteer/proxy-manager.js +478 -0
  124. package/src/plugins/puppeteer/stealth-manager.js +556 -0
  125. package/src/plugins/puppeteer.errors.js +81 -0
  126. package/src/plugins/puppeteer.plugin.js +1327 -0
  127. package/src/plugins/queue-consumer.plugin.js +69 -14
  128. package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
  129. package/src/plugins/recon/concerns/command-runner.js +148 -0
  130. package/src/plugins/recon/concerns/diff-detector.js +372 -0
  131. package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
  132. package/src/plugins/recon/concerns/process-manager.js +338 -0
  133. package/src/plugins/recon/concerns/report-generator.js +478 -0
  134. package/src/plugins/recon/concerns/security-analyzer.js +571 -0
  135. package/src/plugins/recon/concerns/target-normalizer.js +68 -0
  136. package/src/plugins/recon/config/defaults.js +321 -0
  137. package/src/plugins/recon/config/resources.js +370 -0
  138. package/src/plugins/recon/index.js +778 -0
  139. package/src/plugins/recon/managers/dependency-manager.js +174 -0
  140. package/src/plugins/recon/managers/scheduler-manager.js +179 -0
  141. package/src/plugins/recon/managers/storage-manager.js +745 -0
  142. package/src/plugins/recon/managers/target-manager.js +274 -0
  143. package/src/plugins/recon/stages/asn-stage.js +314 -0
  144. package/src/plugins/recon/stages/certificate-stage.js +84 -0
  145. package/src/plugins/recon/stages/dns-stage.js +107 -0
  146. package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
  147. package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
  148. package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
  149. package/src/plugins/recon/stages/http-stage.js +89 -0
  150. package/src/plugins/recon/stages/latency-stage.js +148 -0
  151. package/src/plugins/recon/stages/massdns-stage.js +302 -0
  152. package/src/plugins/recon/stages/osint-stage.js +1373 -0
  153. package/src/plugins/recon/stages/ports-stage.js +169 -0
  154. package/src/plugins/recon/stages/screenshot-stage.js +94 -0
  155. package/src/plugins/recon/stages/secrets-stage.js +514 -0
  156. package/src/plugins/recon/stages/subdomains-stage.js +295 -0
  157. package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
  158. package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
  159. package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
  160. package/src/plugins/recon/stages/whois-stage.js +349 -0
  161. package/src/plugins/recon.plugin.js +75 -0
  162. package/src/plugins/recon.plugin.js.backup +2635 -0
  163. package/src/plugins/relation.errors.js +87 -14
  164. package/src/plugins/replicator.plugin.js +514 -137
  165. package/src/plugins/replicators/base-replicator.class.js +89 -1
  166. package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
  167. package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
  168. package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
  169. package/src/plugins/replicators/mysql-replicator.class.js +52 -17
  170. package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
  171. package/src/plugins/replicators/postgres-replicator.class.js +62 -27
  172. package/src/plugins/replicators/s3db-replicator.class.js +25 -18
  173. package/src/plugins/replicators/schema-sync.helper.js +3 -3
  174. package/src/plugins/replicators/sqs-replicator.class.js +8 -2
  175. package/src/plugins/replicators/turso-replicator.class.js +23 -3
  176. package/src/plugins/replicators/webhook-replicator.class.js +42 -4
  177. package/src/plugins/s3-queue.plugin.js +464 -65
  178. package/src/plugins/scheduler.plugin.js +20 -6
  179. package/src/plugins/state-machine.plugin.js +40 -9
  180. package/src/plugins/tfstate/README.md +126 -126
  181. package/src/plugins/tfstate/base-driver.js +28 -4
  182. package/src/plugins/tfstate/errors.js +65 -10
  183. package/src/plugins/tfstate/filesystem-driver.js +52 -8
  184. package/src/plugins/tfstate/index.js +163 -90
  185. package/src/plugins/tfstate/s3-driver.js +64 -6
  186. package/src/plugins/ttl.plugin.js +72 -17
  187. package/src/plugins/vector/distances.js +18 -12
  188. package/src/plugins/vector/kmeans.js +26 -4
  189. package/src/resource.class.js +115 -19
  190. package/src/testing/factory.class.js +20 -3
  191. package/src/testing/seeder.class.js +7 -1
  192. package/src/clients/memory-client.md +0 -917
  193. package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
@@ -0,0 +1,778 @@
1
+ /**
2
+ * ReconPlugin - Modular Refactored Version
3
+ *
4
+ * Main orchestrator that coordinates managers, stages, and concerns.
5
+ * Backward compatible with the original monolithic API.
6
+ *
7
+ * Architecture:
8
+ * - Managers: Handle high-level operations (storage, targets, scheduling, dependencies)
9
+ * - Stages: Execute individual reconnaissance tasks (DNS, ports, subdomains, etc.)
10
+ * - Concerns: Shared utilities (command runner, normalizer, report generator, etc.)
11
+ */
12
+
13
+ import { Plugin } from '../plugin.class.js';
14
+
15
+ // Managers
16
+ import { StorageManager } from './managers/storage-manager.js';
17
+ import { TargetManager } from './managers/target-manager.js';
18
+ import { SchedulerManager } from './managers/scheduler-manager.js';
19
+ import { DependencyManager } from './managers/dependency-manager.js';
20
+
21
+ // Stages
22
+ import { DnsStage } from './stages/dns-stage.js';
23
+ import { CertificateStage } from './stages/certificate-stage.js';
24
+ import { LatencyStage } from './stages/latency-stage.js';
25
+ import { HttpStage } from './stages/http-stage.js';
26
+ import { PortsStage } from './stages/ports-stage.js';
27
+ import { SubdomainsStage } from './stages/subdomains-stage.js';
28
+ import { WebDiscoveryStage } from './stages/web-discovery-stage.js';
29
+ import { VulnerabilityStage } from './stages/vulnerability-stage.js';
30
+ import { TlsAuditStage } from './stages/tls-audit-stage.js';
31
+ import { FingerprintStage } from './stages/fingerprint-stage.js';
32
+ import { ScreenshotStage } from './stages/screenshot-stage.js';
33
+ import { OsintStage } from './stages/osint-stage.js';
34
+ import { WhoisStage } from './stages/whois-stage.js';
35
+ import { SecretsStage } from './stages/secrets-stage.js';
36
+ import { ASNStage } from './stages/asn-stage.js';
37
+ import { DNSDumpsterStage } from './stages/dnsdumpster-stage.js';
38
+ import { MassDNSStage } from './stages/massdns-stage.js';
39
+ import { GoogleDorksStage } from './stages/google-dorks-stage.js';
40
+
41
+ // Concerns
42
+ import { CommandRunner } from './concerns/command-runner.js';
43
+ import { TargetNormalizer } from './concerns/target-normalizer.js';
44
+ import { FingerprintBuilder } from './concerns/fingerprint-builder.js';
45
+ import { ReportGenerator } from './concerns/report-generator.js';
46
+ import { DiffDetector } from './concerns/diff-detector.js';
47
+ import { SecurityAnalyzer } from './concerns/security-analyzer.js';
48
+ import { processManager } from './concerns/process-manager.js';
49
+
50
+ // Behaviors
51
+ import { UptimeBehavior } from './behaviors/uptime-behavior.js';
52
+
53
+ // Config
54
+ import { DEFAULT_CONFIG, BEHAVIOR_PRESETS } from './config/defaults.js';
55
+
56
+ /**
57
+ * Deep merge two objects
58
+ * @param {Object} target - Target object
59
+ * @param {Object} source - Source object
60
+ * @returns {Object} Merged object
61
+ */
62
+ function deepMerge(target, source) {
63
+ const output = { ...target };
64
+ if (isObject(target) && isObject(source)) {
65
+ Object.keys(source).forEach(key => {
66
+ if (isObject(source[key])) {
67
+ if (!(key in target)) {
68
+ output[key] = source[key];
69
+ } else {
70
+ output[key] = deepMerge(target[key], source[key]);
71
+ }
72
+ } else {
73
+ output[key] = source[key];
74
+ }
75
+ });
76
+ }
77
+ return output;
78
+ }
79
+
80
+ function isObject(item) {
81
+ return item && typeof item === 'object' && !Array.isArray(item);
82
+ }
83
+
84
+ /**
85
+ * ReconPlugin
86
+ *
87
+ * Main plugin class that orchestrates reconnaissance operations.
88
+ */
89
+ export class ReconPlugin extends Plugin {
90
+ static pluginName = 'recon';
91
+
92
+ constructor(config = {}) {
93
+ // Pass config to base class (includes namespace handling)
94
+ super(config);
95
+
96
+ // Apply behavior preset if specified
97
+ let baseConfig = DEFAULT_CONFIG;
98
+ const behaviorMode = config.behavior || 'default';
99
+
100
+ if (config.behavior && BEHAVIOR_PRESETS[config.behavior]) {
101
+ const preset = BEHAVIOR_PRESETS[config.behavior];
102
+ baseConfig = {
103
+ ...DEFAULT_CONFIG,
104
+ ...preset,
105
+ features: {
106
+ ...DEFAULT_CONFIG.features,
107
+ ...preset.features
108
+ }
109
+ };
110
+
111
+ // Emit behavior-applied event
112
+ setTimeout(() => {
113
+ this.emit('recon:behavior-applied', {
114
+ mode: config.behavior,
115
+ preset,
116
+ overrides: config.behaviorOverrides || {},
117
+ final: this.config
118
+ });
119
+ }, 0);
120
+ }
121
+
122
+ // Merge with defaults (and preset if applicable)
123
+ this.config = {
124
+ ...baseConfig,
125
+ ...config,
126
+ behavior: behaviorMode,
127
+ features: deepMerge(
128
+ deepMerge(baseConfig.features, config.features || {}),
129
+ config.behaviorOverrides?.features || {}
130
+ ),
131
+ storage: {
132
+ ...baseConfig.storage,
133
+ ...(config.storage || {})
134
+ }
135
+ };
136
+
137
+ // Initialize command runner
138
+ this.commandRunner = new CommandRunner();
139
+
140
+ // Initialize process manager (for automatic cleanup)
141
+ this.processManager = processManager;
142
+
143
+ // Initialize managers
144
+ this.storageManager = null; // Initialized in initialize()
145
+ this.targetManager = null;
146
+ this.schedulerManager = null;
147
+ this.dependencyManager = new DependencyManager(this);
148
+
149
+ // Initialize stages
150
+ this.stages = {
151
+ dns: new DnsStage(this),
152
+ certificate: new CertificateStage(this),
153
+ latency: new LatencyStage(this),
154
+ http: new HttpStage(this),
155
+ ports: new PortsStage(this),
156
+ subdomains: new SubdomainsStage(this),
157
+ webDiscovery: new WebDiscoveryStage(this),
158
+ vulnerability: new VulnerabilityStage(this),
159
+ tlsAudit: new TlsAuditStage(this),
160
+ fingerprint: new FingerprintStage(this),
161
+ screenshot: new ScreenshotStage(this),
162
+ osint: new OsintStage(this),
163
+ whois: new WhoisStage(this),
164
+ secrets: new SecretsStage(this),
165
+ asn: new ASNStage(this),
166
+ dnsdumpster: new DNSDumpsterStage(this),
167
+ massdns: new MassDNSStage(this),
168
+ googleDorks: new GoogleDorksStage(this)
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Plugin initialization hook
174
+ */
175
+ async initialize() {
176
+ // Initialize managers that need database access
177
+ this.storageManager = new StorageManager(this);
178
+ this.targetManager = new TargetManager(this);
179
+ this.schedulerManager = new SchedulerManager(this);
180
+
181
+ // Initialize uptime behavior if enabled
182
+ if (this.config.behaviors?.uptime?.enabled) {
183
+ this.uptimeBehavior = new UptimeBehavior(this, this.config.behaviors.uptime);
184
+ }
185
+
186
+ // Create plugin storage resources
187
+ await this.storageManager.initialize();
188
+
189
+ // Start scheduler if enabled
190
+ if (this.config.scheduler?.enabled) {
191
+ await this.schedulerManager.start();
192
+ }
193
+
194
+ // Check tool dependencies
195
+ await this.dependencyManager.checkAll();
196
+ }
197
+
198
+ /**
199
+ * Plugin cleanup hook
200
+ */
201
+ async cleanup() {
202
+ // Stop scheduler
203
+ if (this.schedulerManager) {
204
+ await this.schedulerManager.stop();
205
+ }
206
+
207
+ // Stop uptime monitoring
208
+ if (this.uptimeBehavior) {
209
+ this.uptimeBehavior.cleanup();
210
+ }
211
+
212
+ // Clear command runner cache
213
+ this.commandRunner.clearCache();
214
+ }
215
+
216
+ /**
217
+ * Scan a target (main public API)
218
+ *
219
+ * @param {string|object} target - Target URL/domain or normalized target object
220
+ * @param {object} options - Scan options
221
+ * @returns {Promise<object>} Scan report
222
+ */
223
+ async scan(target, options = {}) {
224
+ const startTime = Date.now();
225
+
226
+ // Normalize target
227
+ const normalizedTarget = typeof target === 'string'
228
+ ? TargetNormalizer.normalize(target)
229
+ : target;
230
+
231
+ // Merge options with config
232
+ const scanConfig = {
233
+ ...this.config.features,
234
+ ...options
235
+ };
236
+
237
+ // Execute scan
238
+ const results = {};
239
+
240
+ // DNS stage
241
+ if (scanConfig.dns !== false) {
242
+ results.dns = await this.stages.dns.execute(normalizedTarget, scanConfig.dns);
243
+ }
244
+
245
+ // Certificate stage
246
+ if (scanConfig.certificate !== false) {
247
+ results.certificate = await this.stages.certificate.execute(normalizedTarget, scanConfig.certificate);
248
+ }
249
+
250
+ // WHOIS stage
251
+ if (scanConfig.whois !== false) {
252
+ results.whois = await this.stages.whois.execute(normalizedTarget, scanConfig.whois);
253
+ }
254
+
255
+ // Latency stage
256
+ if (scanConfig.latency !== false) {
257
+ results.latency = await this.stages.latency.execute(normalizedTarget, scanConfig.latency);
258
+ }
259
+
260
+ // HTTP stage
261
+ if (scanConfig.http !== false) {
262
+ results.http = await this.stages.http.execute(normalizedTarget, scanConfig.http);
263
+ }
264
+
265
+ // Ports stage
266
+ if (scanConfig.ports !== false) {
267
+ results.ports = await this.stages.ports.execute(normalizedTarget, scanConfig.ports);
268
+ }
269
+
270
+ // Subdomains stage
271
+ if (scanConfig.subdomains !== false) {
272
+ results.subdomains = await this.stages.subdomains.execute(normalizedTarget, scanConfig.subdomains);
273
+ }
274
+
275
+ // Web discovery stage
276
+ if (scanConfig.webDiscovery !== false) {
277
+ results.webDiscovery = await this.stages.webDiscovery.execute(normalizedTarget, scanConfig.webDiscovery);
278
+ }
279
+
280
+ // Vulnerability stage
281
+ if (scanConfig.vulnerability !== false) {
282
+ results.vulnerability = await this.stages.vulnerability.execute(normalizedTarget, scanConfig.vulnerability);
283
+ }
284
+
285
+ // TLS audit stage
286
+ if (scanConfig.tlsAudit !== false) {
287
+ results.tlsAudit = await this.stages.tlsAudit.execute(normalizedTarget, scanConfig.tlsAudit);
288
+ }
289
+
290
+ // Fingerprint stage
291
+ if (scanConfig.fingerprint !== false) {
292
+ results.fingerprint = await this.stages.fingerprint.execute(normalizedTarget, scanConfig.fingerprint);
293
+ }
294
+
295
+ // Screenshot stage
296
+ if (scanConfig.screenshot !== false) {
297
+ results.screenshot = await this.stages.screenshot.execute(normalizedTarget, scanConfig.screenshot);
298
+ }
299
+
300
+ // OSINT stage
301
+ if (scanConfig.osint !== false) {
302
+ results.osint = await this.stages.osint.execute(normalizedTarget, scanConfig.osint);
303
+ }
304
+
305
+ // Secrets detection stage
306
+ if (scanConfig.secrets !== false) {
307
+ results.secrets = await this.stages.secrets.execute(normalizedTarget, scanConfig.secrets);
308
+ }
309
+
310
+ // ASN stage
311
+ if (scanConfig.asn !== false) {
312
+ results.asn = await this.stages.asn.execute(normalizedTarget, scanConfig.asn);
313
+ }
314
+
315
+ // DNSDumpster stage
316
+ if (scanConfig.dnsdumpster !== false) {
317
+ results.dnsdumpster = await this.stages.dnsdumpster.execute(normalizedTarget, scanConfig.dnsdumpster);
318
+ }
319
+
320
+ // MassDNS stage
321
+ if (scanConfig.massdns !== false) {
322
+ results.massdns = await this.stages.massdns.execute(normalizedTarget, scanConfig.massdns);
323
+ }
324
+
325
+ // Google Dorks stage
326
+ if (scanConfig.googleDorks !== false) {
327
+ results.googleDorks = await this.stages.googleDorks.execute(normalizedTarget, scanConfig.googleDorks);
328
+ }
329
+
330
+ // Build consolidated fingerprint
331
+ const fingerprint = FingerprintBuilder.build(results);
332
+
333
+ // Get uptime status if monitoring is enabled
334
+ let uptimeStatus = null;
335
+ if (this.uptimeBehavior) {
336
+ try {
337
+ uptimeStatus = this.uptimeBehavior.getStatus(normalizedTarget.host);
338
+ } catch (error) {
339
+ // Uptime not monitored for this target, skip
340
+ }
341
+ }
342
+
343
+ // Create report
344
+ const report = {
345
+ id: this._generateReportId(),
346
+ timestamp: new Date().toISOString(),
347
+ target: normalizedTarget,
348
+ duration: Date.now() - startTime,
349
+ status: 'completed',
350
+ results,
351
+ fingerprint,
352
+ uptime: uptimeStatus ? {
353
+ status: uptimeStatus.status,
354
+ uptimePercentage: uptimeStatus.uptimePercentage,
355
+ lastCheck: uptimeStatus.lastCheck,
356
+ isDown: uptimeStatus.isDown,
357
+ consecutiveFails: uptimeStatus.consecutiveFails
358
+ } : null
359
+ };
360
+
361
+ // Persist report if storage enabled and manager is initialized
362
+ if (this.config.storage.enabled && this.storageManager) {
363
+ // Layer 1 + 2: Persist to PluginStorage (raw + aggregated)
364
+ await this.storageManager.persistReport(normalizedTarget, report);
365
+
366
+ // Layer 3: Persist to Database Resources (queryable)
367
+ if (this.config.resources.persist) {
368
+ await this.storageManager.persistToResources(report);
369
+ }
370
+
371
+ // Link report to uptime monitoring if enabled
372
+ if (this.uptimeBehavior && uptimeStatus) {
373
+ await this.uptimeBehavior.linkReportToUptime(
374
+ normalizedTarget.host,
375
+ report.id,
376
+ report.timestamp
377
+ );
378
+ }
379
+ }
380
+
381
+ return report;
382
+ }
383
+
384
+ /**
385
+ * Scan multiple targets in batch
386
+ */
387
+ async batchScan(targets, options = {}) {
388
+ const results = [];
389
+
390
+ for (const target of targets) {
391
+ try {
392
+ const report = await this.scan(target, options);
393
+ results.push(report);
394
+ } catch (error) {
395
+ results.push({
396
+ target: typeof target === 'string' ? target : target.original,
397
+ status: 'error',
398
+ error: error.message
399
+ });
400
+ }
401
+ }
402
+
403
+ return results;
404
+ }
405
+
406
+ /**
407
+ * Get scan report by ID
408
+ */
409
+ async getReport(reportId) {
410
+ return this.storageManager.getReport(reportId);
411
+ }
412
+
413
+ /**
414
+ * List all reports
415
+ */
416
+ async listReports(options = {}) {
417
+ return this.storageManager.listReports(options);
418
+ }
419
+
420
+ /**
421
+ * Get reports for a specific host
422
+ */
423
+ async getReportsByHost(host, options = {}) {
424
+ if (!this.storageManager) {
425
+ return [];
426
+ }
427
+ return this.storageManager.getReportsByHost(host, options);
428
+ }
429
+
430
+ /**
431
+ * Compare two reports and detect changes
432
+ */
433
+ async compareReports(reportId1, reportId2) {
434
+ const [report1, report2] = await Promise.all([
435
+ this.storageManager.getReport(reportId1),
436
+ this.storageManager.getReport(reportId2)
437
+ ]);
438
+
439
+ return DiffDetector.detect(report1, report2);
440
+ }
441
+
442
+ /**
443
+ * Generate markdown report
444
+ */
445
+ generateMarkdownReport(report) {
446
+ return ReportGenerator.generateMarkdown(report);
447
+ }
448
+
449
+ /**
450
+ * Generate JSON report
451
+ */
452
+ generateJSONReport(report) {
453
+ return ReportGenerator.generateJSON(report);
454
+ }
455
+
456
+ /**
457
+ * Generate HTML report
458
+ */
459
+ generateHTMLReport(report) {
460
+ return ReportGenerator.generateHTML(report);
461
+ }
462
+
463
+ /**
464
+ * Generate executive summary
465
+ */
466
+ generateExecutiveSummary(report) {
467
+ return ReportGenerator.generateExecutiveSummary(report);
468
+ }
469
+
470
+ /**
471
+ * Generate security audit checklist from scan report
472
+ * @param {Object} report - Scan report
473
+ * @returns {Object} Security audit with findings and recommendations
474
+ */
475
+ generateSecurityAudit(report) {
476
+ return SecurityAnalyzer.analyze(report);
477
+ }
478
+
479
+ /**
480
+ * Generate security audit markdown report
481
+ * @param {Object} report - Scan report
482
+ * @returns {String} Markdown formatted security audit
483
+ */
484
+ generateSecurityAuditMarkdown(report) {
485
+ const audit = SecurityAnalyzer.analyze(report);
486
+ return SecurityAnalyzer.generateMarkdownReport(audit);
487
+ }
488
+
489
+ /**
490
+ * Add dynamic target for scheduled scanning
491
+ */
492
+ async addTarget(target, schedule = null) {
493
+ return this.targetManager.addTarget(target, schedule);
494
+ }
495
+
496
+ /**
497
+ * Remove dynamic target
498
+ */
499
+ async removeTarget(targetId) {
500
+ return this.targetManager.removeTarget(targetId);
501
+ }
502
+
503
+ /**
504
+ * List all dynamic targets
505
+ */
506
+ async listTargets() {
507
+ return this.targetManager.listTargets();
508
+ }
509
+
510
+ /**
511
+ * Update target schedule
512
+ */
513
+ async updateTargetSchedule(targetId, schedule) {
514
+ return this.targetManager.updateSchedule(targetId, schedule);
515
+ }
516
+
517
+ /**
518
+ * Get tool availability status
519
+ */
520
+ async getToolStatus() {
521
+ return this.dependencyManager.getStatus();
522
+ }
523
+
524
+ /**
525
+ * Check if a specific tool is available
526
+ */
527
+ async isToolAvailable(toolName) {
528
+ return this.commandRunner.isAvailable(toolName);
529
+ }
530
+
531
+ /**
532
+ * Run a scheduled sweep of all targets
533
+ */
534
+ async runScheduledSweep() {
535
+ return this.schedulerManager.runSweep();
536
+ }
537
+
538
+ /**
539
+ * Get diff between latest scans for a host
540
+ */
541
+ async getLatestDiff(host) {
542
+ const reports = await this.getReportsByHost(host, { limit: 2, sort: 'desc' });
543
+
544
+ if (reports.length < 2) {
545
+ return null;
546
+ }
547
+
548
+ return DiffDetector.detect(reports[1], reports[0]);
549
+ }
550
+
551
+ /**
552
+ * Get fingerprint for a host
553
+ */
554
+ async getFingerprint(host) {
555
+ const reports = await this.getReportsByHost(host, { limit: 1 });
556
+
557
+ if (reports.length === 0) {
558
+ return null;
559
+ }
560
+
561
+ return reports[0].fingerprint;
562
+ }
563
+
564
+ /**
565
+ * Generate report ID
566
+ */
567
+ _generateReportId() {
568
+ return `rpt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
569
+ }
570
+
571
+ // ============================================================================
572
+ // UPTIME BEHAVIOR METHODS
573
+ // ============================================================================
574
+
575
+ /**
576
+ * Start monitoring uptime for a target
577
+ */
578
+ async startUptimeMonitoring(target) {
579
+ if (!this.uptimeBehavior) {
580
+ throw new Error('Uptime behavior is not enabled. Set config.behaviors.uptime.enabled = true');
581
+ }
582
+
583
+ const normalizedTarget = typeof target === 'string'
584
+ ? TargetNormalizer.normalize(target)
585
+ : target;
586
+
587
+ return await this.uptimeBehavior.startMonitoring(normalizedTarget);
588
+ }
589
+
590
+ /**
591
+ * Stop monitoring uptime for a target
592
+ */
593
+ stopUptimeMonitoring(host) {
594
+ if (!this.uptimeBehavior) {
595
+ throw new Error('Uptime behavior is not enabled');
596
+ }
597
+
598
+ return this.uptimeBehavior.stopMonitoring(host);
599
+ }
600
+
601
+ /**
602
+ * Get uptime status for a target
603
+ */
604
+ getUptimeStatus(host) {
605
+ if (!this.uptimeBehavior) {
606
+ throw new Error('Uptime behavior is not enabled');
607
+ }
608
+
609
+ return this.uptimeBehavior.getStatus(host);
610
+ }
611
+
612
+ /**
613
+ * Get uptime statuses for all monitored targets
614
+ */
615
+ getAllUptimeStatuses() {
616
+ if (!this.uptimeBehavior) {
617
+ throw new Error('Uptime behavior is not enabled');
618
+ }
619
+
620
+ return this.uptimeBehavior.getAllStatuses();
621
+ }
622
+
623
+ /**
624
+ * Load historical uptime status from storage
625
+ */
626
+ async loadUptimeStatus(host) {
627
+ if (!this.uptimeBehavior) {
628
+ throw new Error('Uptime behavior is not enabled');
629
+ }
630
+
631
+ return await this.uptimeBehavior.loadStatus(host);
632
+ }
633
+
634
+ // ============================================================================
635
+ // BACKWARD COMPATIBILITY METHODS
636
+ // These methods maintain compatibility with the original monolithic API
637
+ // ============================================================================
638
+
639
+ /**
640
+ * Legacy method: runDiagnostics (alias for scan)
641
+ * @deprecated Use scan() instead
642
+ */
643
+ async runDiagnostics(target, options = {}) {
644
+ return this.scan(target, options);
645
+ }
646
+
647
+ /**
648
+ * Legacy method: generateClientReport
649
+ * @deprecated Use generateMarkdownReport() instead
650
+ */
651
+ async generateClientReport(host, format = 'markdown') {
652
+ const reports = await this.getReportsByHost(host, { limit: 1 });
653
+
654
+ if (reports.length === 0) {
655
+ return format === 'json' ? '{}' : '# No reports found';
656
+ }
657
+
658
+ const report = reports[0];
659
+
660
+ if (format === 'json') {
661
+ return this.generateJSONReport(report);
662
+ }
663
+
664
+ return this.generateMarkdownReport(report);
665
+ }
666
+
667
+ /**
668
+ * Legacy method: _runWebDiscovery (now part of stages)
669
+ * @deprecated Access via stages.webDiscovery.execute() instead
670
+ */
671
+ async _runWebDiscovery(target, config) {
672
+ return this.stages.webDiscovery.execute(target, config);
673
+ }
674
+
675
+ /**
676
+ * Legacy method: _emitDiffAlerts
677
+ * @deprecated Use compareReports() and handle alerts manually
678
+ */
679
+ async _emitDiffAlerts(host, report, diffs) {
680
+ for (const diff of diffs) {
681
+ if (diff.severity === 'critical' || diff.severity === 'high') {
682
+ this.emit('recon:alert', {
683
+ host,
684
+ severity: diff.severity,
685
+ change: diff.change,
686
+ timestamp: report.timestamp
687
+ });
688
+ }
689
+ }
690
+ }
691
+
692
+ /**
693
+ * Legacy method: _applyRateLimit
694
+ * @deprecated Rate limiting is now handled automatically
695
+ */
696
+ async _applyRateLimit(stageName) {
697
+ if (!this.config.rateLimit?.enabled) {
698
+ return;
699
+ }
700
+
701
+ const delay = this.config.rateLimit.delayBetweenStages || 1000;
702
+
703
+ this.emit('recon:rate-limit-delay', {
704
+ stage: stageName,
705
+ delayMs: delay
706
+ });
707
+
708
+ await new Promise(resolve => setTimeout(resolve, delay));
709
+ }
710
+
711
+ /**
712
+ * Legacy method: _getResource (proxy to database)
713
+ * @deprecated Access via database.getResource() directly
714
+ */
715
+ async _getResource(resourceName) {
716
+ if (!this.database) {
717
+ return null;
718
+ }
719
+
720
+ const fullName = `plg_recon_${resourceName}`;
721
+
722
+ try {
723
+ return await this.database.getResource(fullName);
724
+ } catch (error) {
725
+ return null;
726
+ }
727
+ }
728
+
729
+ /**
730
+ * Lifecycle hook: onStop
731
+ * Cleanup all spawned processes when plugin stops
732
+ */
733
+ async onStop() {
734
+ console.log('[ReconPlugin] Stopping plugin, cleaning up processes...');
735
+ await this.processManager.cleanup({ silent: false });
736
+ }
737
+
738
+ /**
739
+ * Lifecycle hook: onUninstall
740
+ * Cleanup all resources when plugin is uninstalled
741
+ */
742
+ async onUninstall(options = {}) {
743
+ console.log('[ReconPlugin] Uninstalling plugin, cleaning up processes...');
744
+ await this.processManager.forceCleanup();
745
+ }
746
+
747
+ /**
748
+ * Legacy hook: afterInstall
749
+ * Registers legacy alias database.plugins.network
750
+ */
751
+ afterInstall() {
752
+ super.afterInstall();
753
+
754
+ // Register legacy alias
755
+ if (this.database) {
756
+ this.database.plugins.network = this;
757
+ }
758
+ }
759
+
760
+ /**
761
+ * Legacy hook: afterUninstall
762
+ * Removes legacy alias database.plugins.network
763
+ */
764
+ afterUninstall() {
765
+ super.afterUninstall();
766
+
767
+ // Cleanup processes
768
+ this.processManager.cleanup({ silent: true }).catch(() => {});
769
+
770
+ // Remove legacy alias
771
+ if (this.database && this.database.plugins.network === this) {
772
+ delete this.database.plugins.network;
773
+ }
774
+ }
775
+ }
776
+
777
+ // Export for backward compatibility
778
+ export default ReconPlugin;