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,478 @@
1
+ /**
2
+ * ReportGenerator
3
+ *
4
+ * Client-facing report generation:
5
+ * - Markdown reports (human-readable)
6
+ * - JSON reports (machine-readable)
7
+ * - HTML reports (browser-friendly)
8
+ * - Executive summaries
9
+ */
10
+
11
+ export class ReportGenerator {
12
+ /**
13
+ * Generate markdown report from scan results
14
+ */
15
+ static generateMarkdown(report) {
16
+ let markdown = '';
17
+
18
+ // Header
19
+ markdown += `# Reconnaissance Report: ${report.target.host}\n\n`;
20
+ markdown += `**Scan Date:** ${new Date(report.timestamp).toLocaleString()}\n`;
21
+ markdown += `**Target:** ${report.target.original}\n`;
22
+ markdown += `**Duration:** ${report.duration}ms\n`;
23
+ markdown += `**Status:** ${report.status}\n\n`;
24
+
25
+ // Executive Summary
26
+ markdown += '## Executive Summary\n\n';
27
+ markdown += this._generateExecutiveSummary(report);
28
+ markdown += '\n\n';
29
+
30
+ // Infrastructure
31
+ if (report.results?.dns || report.results?.certificate) {
32
+ markdown += '## Infrastructure\n\n';
33
+ if (report.results.dns) {
34
+ markdown += this._generateDnsSection(report.results.dns);
35
+ }
36
+ if (report.results.certificate) {
37
+ markdown += this._generateCertificateSection(report.results.certificate);
38
+ }
39
+ if (report.results.latency) {
40
+ markdown += this._generateLatencySection(report.results.latency);
41
+ }
42
+ markdown += '\n';
43
+ }
44
+
45
+ // Attack Surface
46
+ if (report.results?.ports || report.results?.subdomains || report.results?.webDiscovery) {
47
+ markdown += '## Attack Surface\n\n';
48
+ if (report.results.ports) {
49
+ markdown += this._generatePortsSection(report.results.ports);
50
+ }
51
+ if (report.results.subdomains) {
52
+ markdown += this._generateSubdomainsSection(report.results.subdomains);
53
+ }
54
+ if (report.results.webDiscovery) {
55
+ markdown += this._generateWebDiscoverySection(report.results.webDiscovery);
56
+ }
57
+ markdown += '\n';
58
+ }
59
+
60
+ // Technologies
61
+ if (report.results?.fingerprint || report.results?.http) {
62
+ markdown += '## Technologies\n\n';
63
+ if (report.results.http) {
64
+ markdown += this._generateHttpSection(report.results.http);
65
+ }
66
+ if (report.results.fingerprint) {
67
+ markdown += this._generateFingerprintSection(report.results.fingerprint);
68
+ }
69
+ markdown += '\n';
70
+ }
71
+
72
+ // Security
73
+ if (report.results?.tlsAudit || report.results?.vulnerability) {
74
+ markdown += '## Security\n\n';
75
+ if (report.results.tlsAudit) {
76
+ markdown += this._generateTlsAuditSection(report.results.tlsAudit);
77
+ }
78
+ if (report.results.vulnerability) {
79
+ markdown += this._generateVulnerabilitySection(report.results.vulnerability);
80
+ }
81
+ markdown += '\n';
82
+ }
83
+
84
+ // Screenshots
85
+ if (report.results?.screenshot) {
86
+ markdown += '## Visual Reconnaissance\n\n';
87
+ markdown += this._generateScreenshotSection(report.results.screenshot);
88
+ markdown += '\n';
89
+ }
90
+
91
+ // OSINT
92
+ if (report.results?.osint) {
93
+ markdown += '## OSINT\n\n';
94
+ markdown += this._generateOsintSection(report.results.osint);
95
+ markdown += '\n';
96
+ }
97
+
98
+ return markdown;
99
+ }
100
+
101
+ static _generateExecutiveSummary(report) {
102
+ const summary = [];
103
+ const results = report.results || {};
104
+
105
+ // Count findings
106
+ const openPorts = results.ports?.openPorts?.length || 0;
107
+ const subdomains = results.subdomains?.total || 0;
108
+ const technologies = results.fingerprint?.technologies?.length || 0;
109
+
110
+ summary.push(`- **Open Ports:** ${openPorts}`);
111
+ summary.push(`- **Subdomains:** ${subdomains}`);
112
+ summary.push(`- **Technologies Detected:** ${technologies}`);
113
+
114
+ if (results.certificate) {
115
+ summary.push(`- **Certificate:** ${results.certificate.issuer?.O || 'Unknown'}`);
116
+ }
117
+
118
+ return summary.join('\n');
119
+ }
120
+
121
+ static _generateDnsSection(dns) {
122
+ let section = '### DNS Records\n\n';
123
+
124
+ if (dns.records?.A?.length) {
125
+ section += `**IPv4 Addresses (A):**\n\`\`\`\n${dns.records.A.join('\n')}\n\`\`\`\n\n`;
126
+ }
127
+
128
+ if (dns.records?.AAAA?.length) {
129
+ section += `**IPv6 Addresses (AAAA):**\n\`\`\`\n${dns.records.AAAA.join('\n')}\n\`\`\`\n\n`;
130
+ }
131
+
132
+ if (dns.records?.NS?.length) {
133
+ section += `**Nameservers (NS):**\n\`\`\`\n${dns.records.NS.join('\n')}\n\`\`\`\n\n`;
134
+ }
135
+
136
+ if (dns.records?.MX?.length) {
137
+ section += `**Mail Servers (MX):**\n\`\`\`\n${dns.records.MX.map(mx => `${mx.priority} ${mx.exchange}`).join('\n')}\n\`\`\`\n\n`;
138
+ }
139
+
140
+ if (dns.records?.TXT?.length) {
141
+ section += `**TXT Records:**\n\`\`\`\n${dns.records.TXT.join('\n')}\n\`\`\`\n\n`;
142
+ }
143
+
144
+ return section;
145
+ }
146
+
147
+ static _generateCertificateSection(cert) {
148
+ let section = '### TLS Certificate\n\n';
149
+ section += `- **Subject:** ${JSON.stringify(cert.subject)}\n`;
150
+ section += `- **Issuer:** ${JSON.stringify(cert.issuer)}\n`;
151
+ section += `- **Valid From:** ${cert.validFrom}\n`;
152
+ section += `- **Valid To:** ${cert.validTo}\n`;
153
+ section += `- **Fingerprint:** \`${cert.fingerprint}\`\n`;
154
+
155
+ if (cert.subjectAltName?.length) {
156
+ section += `- **SANs:** ${cert.subjectAltName.join(', ')}\n`;
157
+ }
158
+
159
+ section += '\n';
160
+ return section;
161
+ }
162
+
163
+ static _generateLatencySection(latency) {
164
+ let section = '### Network Latency\n\n';
165
+
166
+ if (latency.ping) {
167
+ section += `**Ping:**\n`;
168
+ section += `- Min: ${latency.ping.min}ms\n`;
169
+ section += `- Avg: ${latency.ping.avg}ms\n`;
170
+ section += `- Max: ${latency.ping.max}ms\n`;
171
+ section += `- Packet Loss: ${latency.ping.packetLoss}%\n\n`;
172
+ }
173
+
174
+ if (latency.traceroute?.hops?.length) {
175
+ section += `**Traceroute:** ${latency.traceroute.hops.length} hops\n\n`;
176
+ }
177
+
178
+ return section;
179
+ }
180
+
181
+ static _generatePortsSection(ports) {
182
+ let section = '### Open Ports\n\n';
183
+
184
+ if (ports.openPorts?.length) {
185
+ section += `**Total:** ${ports.openPorts.length}\n\n`;
186
+ section += '| Port | Protocol | Service | State |\n';
187
+ section += '|------|----------|---------|-------|\n';
188
+ ports.openPorts.forEach(port => {
189
+ section += `| ${port.port} | ${port.protocol || 'tcp'} | ${port.service || '-'} | ${port.state || 'open'} |\n`;
190
+ });
191
+ section += '\n';
192
+ } else {
193
+ section += '*No open ports detected*\n\n';
194
+ }
195
+
196
+ if (ports.scanners) {
197
+ section += `**Scanners Used:** ${Object.keys(ports.scanners).join(', ')}\n\n`;
198
+ }
199
+
200
+ return section;
201
+ }
202
+
203
+ static _generateSubdomainsSection(subdomains) {
204
+ let section = '### Subdomains\n\n';
205
+ section += `**Total:** ${subdomains.total}\n\n`;
206
+
207
+ if (subdomains.list?.length) {
208
+ const displayCount = Math.min(50, subdomains.list.length);
209
+ section += '```\n';
210
+ section += subdomains.list.slice(0, displayCount).join('\n');
211
+ if (subdomains.list.length > displayCount) {
212
+ section += `\n... (${subdomains.list.length - displayCount} more)`;
213
+ }
214
+ section += '\n```\n\n';
215
+ }
216
+
217
+ if (subdomains.sources) {
218
+ section += `**Sources:** ${Object.keys(subdomains.sources).join(', ')}\n\n`;
219
+ }
220
+
221
+ return section;
222
+ }
223
+
224
+ static _generateWebDiscoverySection(web) {
225
+ let section = '### Discovered Paths\n\n';
226
+
227
+ const allPaths = new Set();
228
+ Object.values(web.tools || {}).forEach(tool => {
229
+ if (tool.status === 'ok' && tool.paths) {
230
+ tool.paths.forEach(path => allPaths.add(path));
231
+ }
232
+ });
233
+
234
+ if (allPaths.size > 0) {
235
+ section += `**Total:** ${allPaths.size}\n\n`;
236
+ const displayCount = Math.min(30, allPaths.size);
237
+ section += '```\n';
238
+ section += Array.from(allPaths).slice(0, displayCount).join('\n');
239
+ if (allPaths.size > displayCount) {
240
+ section += `\n... (${allPaths.size - displayCount} more)`;
241
+ }
242
+ section += '\n```\n\n';
243
+ } else {
244
+ section += '*No paths discovered*\n\n';
245
+ }
246
+
247
+ if (web.tools) {
248
+ section += `**Tools Used:** ${Object.keys(web.tools).join(', ')}\n\n`;
249
+ }
250
+
251
+ return section;
252
+ }
253
+
254
+ static _generateHttpSection(http) {
255
+ let section = '### HTTP Headers\n\n';
256
+
257
+ if (http.headers?.server) {
258
+ section += `- **Server:** ${http.headers.server}\n`;
259
+ }
260
+
261
+ if (http.headers?.['x-powered-by']) {
262
+ section += `- **Powered By:** ${http.headers['x-powered-by']}\n`;
263
+ }
264
+
265
+ if (http.headers) {
266
+ const securityHeaders = [
267
+ 'strict-transport-security',
268
+ 'content-security-policy',
269
+ 'x-frame-options',
270
+ 'x-content-type-options',
271
+ 'x-xss-protection'
272
+ ];
273
+
274
+ const found = securityHeaders.filter(h => http.headers[h]);
275
+ if (found.length > 0) {
276
+ section += `- **Security Headers:** ${found.length}/${securityHeaders.length}\n`;
277
+ }
278
+ }
279
+
280
+ section += '\n';
281
+ return section;
282
+ }
283
+
284
+ static _generateFingerprintSection(fingerprint) {
285
+ let section = '### Technology Fingerprint\n\n';
286
+
287
+ if (fingerprint.technologies?.length) {
288
+ section += `**Detected Technologies:**\n`;
289
+ fingerprint.technologies.forEach(tech => {
290
+ section += `- ${tech}\n`;
291
+ });
292
+ section += '\n';
293
+ }
294
+
295
+ if (fingerprint.cms) {
296
+ section += `**CMS:** ${fingerprint.cms}\n\n`;
297
+ }
298
+
299
+ if (fingerprint.frameworks?.length) {
300
+ section += `**Frameworks:** ${fingerprint.frameworks.join(', ')}\n\n`;
301
+ }
302
+
303
+ return section;
304
+ }
305
+
306
+ static _generateTlsAuditSection(tls) {
307
+ let section = '### TLS/SSL Audit\n\n';
308
+
309
+ if (tls.grade) {
310
+ section += `**Grade:** ${tls.grade}\n\n`;
311
+ }
312
+
313
+ if (tls.tools) {
314
+ section += `**Tools Used:** ${Object.keys(tls.tools).join(', ')}\n\n`;
315
+ }
316
+
317
+ return section;
318
+ }
319
+
320
+ static _generateVulnerabilitySection(vuln) {
321
+ let section = '### Vulnerabilities\n\n';
322
+
323
+ let totalVulns = 0;
324
+ Object.entries(vuln.tools || {}).forEach(([tool, result]) => {
325
+ if (result.status === 'ok' && result.vulnerabilities) {
326
+ totalVulns += result.vulnerabilities.length;
327
+ }
328
+ });
329
+
330
+ if (totalVulns > 0) {
331
+ section += `**Total Vulnerabilities:** ${totalVulns}\n\n`;
332
+ } else {
333
+ section += '*No vulnerabilities detected*\n\n';
334
+ }
335
+
336
+ if (vuln.tools) {
337
+ section += `**Scanners Used:** ${Object.keys(vuln.tools).join(', ')}\n\n`;
338
+ }
339
+
340
+ return section;
341
+ }
342
+
343
+ static _generateScreenshotSection(screenshot) {
344
+ let section = '### Screenshots\n\n';
345
+
346
+ Object.entries(screenshot.tools || {}).forEach(([tool, result]) => {
347
+ if (result.status === 'ok' && result.outputDir) {
348
+ section += `- **${tool}:** \`${result.outputDir}\`\n`;
349
+ }
350
+ });
351
+
352
+ section += '\n';
353
+ return section;
354
+ }
355
+
356
+ static _generateOsintSection(osint) {
357
+ let section = '### OSINT Data\n\n';
358
+
359
+ if (osint.tools) {
360
+ section += `**Tools Used:** ${Object.keys(osint.tools).join(', ')}\n\n`;
361
+ }
362
+
363
+ return section;
364
+ }
365
+
366
+ /**
367
+ * Generate JSON report (structured data)
368
+ */
369
+ static generateJSON(report) {
370
+ return JSON.stringify(report, null, 2);
371
+ }
372
+
373
+ /**
374
+ * Generate HTML report
375
+ */
376
+ static generateHTML(report) {
377
+ const markdown = this.generateMarkdown(report);
378
+
379
+ // Simple HTML wrapper (in production, use a proper markdown-to-HTML library)
380
+ const html = `
381
+ <!DOCTYPE html>
382
+ <html lang="en">
383
+ <head>
384
+ <meta charset="UTF-8">
385
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
386
+ <title>Recon Report: ${report.target.host}</title>
387
+ <style>
388
+ body {
389
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
390
+ max-width: 900px;
391
+ margin: 40px auto;
392
+ padding: 20px;
393
+ line-height: 1.6;
394
+ color: #333;
395
+ }
396
+ h1 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }
397
+ h2 { color: #34495e; border-bottom: 2px solid #ecf0f1; padding-bottom: 8px; margin-top: 30px; }
398
+ h3 { color: #7f8c8d; margin-top: 20px; }
399
+ code { background: #f8f9fa; padding: 2px 6px; border-radius: 3px; font-family: monospace; }
400
+ pre { background: #f8f9fa; padding: 15px; border-radius: 5px; overflow-x: auto; }
401
+ table { border-collapse: collapse; width: 100%; margin: 15px 0; }
402
+ th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
403
+ th { background: #3498db; color: white; }
404
+ tr:nth-child(even) { background: #f8f9fa; }
405
+ </style>
406
+ </head>
407
+ <body>
408
+ <pre>${markdown.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>
409
+ </body>
410
+ </html>
411
+ `.trim();
412
+
413
+ return html;
414
+ }
415
+
416
+ /**
417
+ * Generate executive summary (high-level overview)
418
+ */
419
+ static generateExecutiveSummary(report) {
420
+ const summary = {
421
+ target: report.target.host,
422
+ scanDate: report.timestamp,
423
+ status: report.status,
424
+ duration: report.duration,
425
+ findings: {
426
+ openPorts: report.results?.ports?.openPorts?.length || 0,
427
+ subdomains: report.results?.subdomains?.total || 0,
428
+ technologies: report.results?.fingerprint?.technologies?.length || 0,
429
+ vulnerabilities: this._countVulnerabilities(report.results?.vulnerability)
430
+ },
431
+ riskLevel: this._calculateRiskLevel(report),
432
+ recommendations: this._generateRecommendations(report)
433
+ };
434
+
435
+ return summary;
436
+ }
437
+
438
+ static _countVulnerabilities(vulnData) {
439
+ if (!vulnData) return 0;
440
+ let count = 0;
441
+ Object.values(vulnData.tools || {}).forEach(tool => {
442
+ if (tool.status === 'ok' && tool.vulnerabilities) {
443
+ count += tool.vulnerabilities.length;
444
+ }
445
+ });
446
+ return count;
447
+ }
448
+
449
+ static _calculateRiskLevel(report) {
450
+ const openPorts = report.results?.ports?.openPorts?.length || 0;
451
+ const vulns = this._countVulnerabilities(report.results?.vulnerability);
452
+
453
+ if (vulns > 5 || openPorts > 20) return 'high';
454
+ if (vulns > 0 || openPorts > 10) return 'medium';
455
+ return 'low';
456
+ }
457
+
458
+ static _generateRecommendations(report) {
459
+ const recommendations = [];
460
+
461
+ const openPorts = report.results?.ports?.openPorts?.length || 0;
462
+ if (openPorts > 10) {
463
+ recommendations.push('Review and close unnecessary open ports');
464
+ }
465
+
466
+ const vulns = this._countVulnerabilities(report.results?.vulnerability);
467
+ if (vulns > 0) {
468
+ recommendations.push('Address identified vulnerabilities immediately');
469
+ }
470
+
471
+ const hasHSTS = report.results?.http?.headers?.['strict-transport-security'];
472
+ if (!hasHSTS) {
473
+ recommendations.push('Enable HSTS (HTTP Strict Transport Security)');
474
+ }
475
+
476
+ return recommendations;
477
+ }
478
+ }