@slicedearth/whoisleuth-cli 2.3.0 → 2.5.1

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 (418) hide show
  1. package/NOTICE +8 -2
  2. package/README.md +19 -15
  3. package/bin/whoisleuth.mjs +8 -1
  4. package/cli/archive-content-digest.mjs +14 -0
  5. package/cli/archive-inspect.mjs +20 -53
  6. package/cli/argument-values.mjs +55 -0
  7. package/cli/arguments.mjs +24 -408
  8. package/cli/artifact-validation/case-response.mjs +65 -44
  9. package/cli/artifact-validation/investigation-capsule.mjs +52 -31
  10. package/cli/artifact-validation/lookup-evidence.mjs +15 -9
  11. package/cli/artifact-validation/signed-review.mjs +136 -68
  12. package/cli/artifact-validation/structure-primitives.mjs +1 -105
  13. package/cli/artifact-verify.mjs +92 -24
  14. package/cli/assurance-arguments.mjs +56 -0
  15. package/cli/assurance-command-definitions.mjs +179 -0
  16. package/cli/assurance-command-runner.mjs +40 -5
  17. package/cli/bagit-folder.mjs +57 -0
  18. package/cli/bagit-review.mjs +23 -0
  19. package/cli/bounded-json.mjs +1 -1
  20. package/cli/bulk-checkpoint.mjs +1 -1
  21. package/cli/bulk-command-runner.mjs +4 -2
  22. package/cli/bulk-output.mjs +29 -3
  23. package/cli/bulk.mjs +2 -3
  24. package/cli/case-command.mjs +212 -0
  25. package/cli/case-pack.mjs +50 -32
  26. package/cli/ci-report.mjs +6 -3
  27. package/cli/collection-arguments.mjs +123 -0
  28. package/cli/collection-command-definitions.mjs +330 -0
  29. package/cli/collection-preflight.mjs +8 -1
  30. package/cli/command-argument-grammar.mjs +8 -206
  31. package/cli/command-definition.mjs +329 -0
  32. package/cli/command-reference.mjs +94 -1357
  33. package/cli/command-seeds.mjs +18 -0
  34. package/cli/compare.mjs +1 -1
  35. package/cli/completion.mjs +298 -79
  36. package/cli/config-profile.mjs +8 -6
  37. package/cli/ct-event-intake.mjs +16 -16
  38. package/cli/discover.mjs +5 -4
  39. package/cli/discovery-observation-snapshot.mjs +46 -18
  40. package/cli/discovery-scan-command-runner.mjs +5 -3
  41. package/cli/discovery-scan.mjs +7 -4
  42. package/cli/discovery-snapshot.mjs +2 -2
  43. package/cli/discovery-workflow.mjs +5 -5
  44. package/cli/domain-control-monitor.mjs +50 -20
  45. package/cli/domain-control-observations.mjs +151 -103
  46. package/cli/errors.mjs +37 -6
  47. package/cli/evidence-arguments.mjs +46 -0
  48. package/cli/evidence-command-definitions.mjs +69 -0
  49. package/cli/evidence-command-runner.mjs +18 -8
  50. package/cli/evidence-signing.mjs +5 -4
  51. package/cli/external-observation-mapping.mjs +9 -10
  52. package/cli/formatters/terminal-command-formats.mjs +6 -0
  53. package/cli/formatters/terminal-lookup.mjs +24 -46
  54. package/cli/formatters/terminal-shared.mjs +5 -3
  55. package/cli/formatters/terminal-technology.mjs +114 -0
  56. package/cli/history-arguments.mjs +39 -0
  57. package/cli/history-command-definitions.mjs +88 -0
  58. package/cli/indicator-set-command.mjs +33 -0
  59. package/cli/inline-command-families.mjs +6 -46
  60. package/cli/inline-command-runner.mjs +4 -31
  61. package/cli/input.mjs +2 -2
  62. package/cli/intake-command.mjs +107 -0
  63. package/cli/interactive-launcher.mjs +2 -160
  64. package/cli/interchange-report.mjs +8 -10
  65. package/cli/investigation-artifacts.mjs +176 -0
  66. package/cli/investigation-checkpoint.mjs +10 -0
  67. package/cli/investigation-folder.mjs +114 -0
  68. package/cli/investigation-manifest.mjs +1 -112
  69. package/cli/investigation-package-review.mjs +103 -0
  70. package/cli/investigation-plan.mjs +38 -147
  71. package/cli/investigation-recipes.mjs +177 -0
  72. package/cli/investigation-run.mjs +256 -35
  73. package/cli/local-document-checkpoint.mjs +170 -0
  74. package/cli/local-mmdb-review.mjs +197 -17
  75. package/cli/lookalike-calibration.mjs +1 -1
  76. package/cli/lookup-brief.mjs +2 -2
  77. package/cli/lookup-browser.mjs +5 -12
  78. package/cli/lookup-command-runner.mjs +33 -39
  79. package/cli/lookup-diff.mjs +47 -12
  80. package/cli/lookup-plan.mjs +16 -14
  81. package/cli/lookup-reconcile.mjs +15 -12
  82. package/cli/lookup-timeline.mjs +7 -6
  83. package/cli/mail-header-review.mjs +24 -247
  84. package/cli/mail-review.mjs +75 -21
  85. package/cli/manual.mjs +1 -0
  86. package/cli/network-arguments.mjs +51 -0
  87. package/cli/network-command-definitions.mjs +130 -0
  88. package/cli/network-command-runner.mjs +45 -31
  89. package/cli/offline-evidence-review.mjs +39 -6
  90. package/cli/output-file.mjs +31 -5
  91. package/cli/posture.mjs +1 -1
  92. package/cli/registry-doctor.mjs +3 -1
  93. package/cli/registry-fixture-scaffold.mjs +1 -1
  94. package/cli/registry-support.mjs +1 -1
  95. package/cli/retained-artifact-diff.mjs +10 -9
  96. package/cli/review-arguments.mjs +131 -0
  97. package/cli/review-command-definitions.mjs +273 -0
  98. package/cli/review-command-runner.mjs +104 -149
  99. package/cli/risk-calibration.mjs +8 -8
  100. package/cli/runner.mjs +74 -37
  101. package/cli/saved-lookup.mjs +2 -2
  102. package/cli/selected-input-worker.mjs +63 -0
  103. package/cli/sharing-review.mjs +8 -80
  104. package/cli/signer-trust.mjs +104 -0
  105. package/cli/source-reliability.mjs +75 -84
  106. package/cli/support-arguments.mjs +49 -0
  107. package/cli/support-command-definitions.mjs +209 -0
  108. package/cli/support-command-runner.mjs +2 -2
  109. package/cli/terminal-input.mjs +168 -0
  110. package/cli/workflow-arguments.mjs +86 -0
  111. package/cli/workflow-command-definitions.mjs +78 -0
  112. package/cli/workflow-command-runner.mjs +75 -13
  113. package/docs/cli-reference.md +103 -30
  114. package/docs/cli.md +510 -25
  115. package/docs/contextual-reviews.md +155 -0
  116. package/lib/abort.mjs +4 -1
  117. package/lib/analyst-taxonomy.mjs +2 -40
  118. package/lib/application-version.mjs +1 -1
  119. package/lib/availability.mjs +27 -754
  120. package/lib/bounded-contract-normalizers.mjs +4 -0
  121. package/lib/bounded-file.mjs +3 -1
  122. package/lib/bounded-html-document.mjs +125 -0
  123. package/lib/bounded-json.mjs +2 -290
  124. package/lib/browser-library-profile.mjs +99 -130
  125. package/lib/browser-library-worker.mjs +112 -0
  126. package/lib/candidate-provenance-bounds.mjs +2 -0
  127. package/lib/classify.mjs +1 -1
  128. package/lib/client-behavior-profile.mjs +3 -3
  129. package/lib/ct-query.mjs +2 -27
  130. package/lib/ct-response-bounds.mjs +2 -9
  131. package/lib/ct-search.mjs +89 -46
  132. package/lib/dmarc-discovery.mjs +62 -0
  133. package/lib/dns-convergence-review.mjs +21 -8
  134. package/lib/dns-delegation-health.mjs +36 -22
  135. package/lib/dns-inheritance-review.mjs +207 -0
  136. package/lib/dns-intelligence.mjs +44 -29
  137. package/lib/dns-mx.mjs +1 -1
  138. package/lib/dns-query-coverage.mjs +40 -0
  139. package/lib/dnssec-evidence-validation.mjs +11 -3
  140. package/lib/domain-assurance.mjs +1 -1
  141. package/lib/domain-change-packet.mjs +18 -14
  142. package/lib/domain-change-review.mjs +40 -16
  143. package/lib/domain-control-flight-recorder.mjs +301 -124
  144. package/lib/domain-control-manifest.mjs +126 -58
  145. package/lib/domain-posture-analysis.mjs +41 -11
  146. package/lib/domain-posture-parsers.mjs +88 -6
  147. package/lib/domain-posture.mjs +120 -32
  148. package/lib/domain-registration.mjs +392 -0
  149. package/lib/evidence-export-privacy.mjs +568 -0
  150. package/lib/evidence-export.mjs +12 -593
  151. package/lib/evidence-report.mjs +7 -2
  152. package/lib/external-intelligence-risk.mjs +2 -124
  153. package/lib/favicon.mjs +117 -41
  154. package/lib/generated/cisa-kev-catalog.mjs +50 -4
  155. package/lib/generated/registrar-standing-catalogue.mjs +18 -10
  156. package/lib/generated/retire-browser-catalog.mjs +2742 -1034
  157. package/lib/generated/{unicode-confusables-17.mjs → unicode-confusables.mjs} +33 -33
  158. package/lib/html-signals.mjs +87 -85
  159. package/lib/http-evidence-bounds.mjs +2 -7
  160. package/lib/http-intelligence.mjs +52 -27
  161. package/lib/idn-confusable-policy.mjs +6 -4
  162. package/lib/idn-confusables.mjs +1 -1
  163. package/lib/interchange-fidelity-registry.mjs +10 -0
  164. package/lib/lookup-cache.mjs +34 -11
  165. package/lib/lookup-child-profile-contract.mjs +24 -15
  166. package/lib/lookup-contract-primitives.mjs +1 -1
  167. package/lib/lookup-diagnostics.mjs +2 -1
  168. package/lib/lookup-network-evidence-bounds.mjs +1 -10
  169. package/lib/lookup-progress.mjs +79 -13
  170. package/lib/lookup-response-contract.mjs +1077 -0
  171. package/lib/lookup-response.mjs +11 -24
  172. package/lib/lookup-source-progress.mjs +24 -35
  173. package/lib/lookup.mjs +49 -28
  174. package/lib/observed-network-context.mjs +43 -27
  175. package/lib/opportunity-scoring.mjs +2 -107
  176. package/lib/outbound-identity.mjs +1 -1
  177. package/lib/outbound-request-bounds.mjs +4 -1
  178. package/lib/page-fingerprints.mjs +87 -134
  179. package/lib/page-role-profile.mjs +12 -8
  180. package/lib/perceptual-hash-comparison.mjs +2 -34
  181. package/lib/perceptual-hash.mjs +79 -24
  182. package/lib/portable-generator.mjs +2 -29
  183. package/lib/project-metadata.mjs +2 -8
  184. package/lib/rdap-bootstrap.mjs +72 -22
  185. package/lib/rdap-client.mjs +26 -14
  186. package/lib/rdap-normalization.mjs +33 -18
  187. package/lib/rdap-search-workbench.mjs +1 -1
  188. package/lib/rdap-transport.mjs +47 -20
  189. package/lib/rdap-types.mjs +2 -1
  190. package/lib/rdap.mjs +18 -3
  191. package/lib/registrable-domain.mjs +2 -36
  192. package/lib/registrar-standing-contract.mjs +2 -1
  193. package/lib/registrar-standing.mjs +9 -13
  194. package/lib/registry-capabilities.mjs +7 -3
  195. package/lib/registry-capability-catalogue.mjs +29 -20
  196. package/lib/registry-dates.mjs +2 -190
  197. package/lib/registry-insights.mjs +56 -18
  198. package/lib/response-policy.mjs +86 -48
  199. package/lib/risk-calibration-summary.mjs +2 -338
  200. package/lib/risk-scoring.mjs +2 -345
  201. package/lib/rpki-evidence.mjs +8 -5
  202. package/lib/safe-fetch.mjs +54 -47
  203. package/lib/scoring-evidence-quality.mjs +2 -107
  204. package/lib/security-txt.mjs +10 -7
  205. package/lib/semantic-version.mjs +2 -54
  206. package/lib/service-binding-dns.mjs +35 -0
  207. package/lib/smtp-transport-review.mjs +75 -34
  208. package/lib/sslbl-certificates.generated.mjs +141 -138
  209. package/lib/static-html-analysis.mjs +117 -146
  210. package/lib/structured-data-identity.mjs +2 -1
  211. package/lib/technology-markup.mjs +100 -0
  212. package/lib/threat-intelligence-manifests.mjs +11 -139
  213. package/lib/threat-intelligence-runtime.mjs +24 -52
  214. package/lib/threat-intelligence-targets.mjs +6 -34
  215. package/lib/threat-intelligence-types.mjs +2 -36
  216. package/lib/typosquat-generator.mjs +29 -16
  217. package/lib/urlhaus-intelligence.mjs +8 -3
  218. package/lib/urlscan-intelligence.mjs +1 -1
  219. package/lib/website-enrichment.mjs +388 -0
  220. package/lib/website-security-posture.mjs +30 -6
  221. package/lib/website-technology.mjs +111 -71
  222. package/lib/whois-authority.mjs +55 -5
  223. package/lib/whois-chain.mjs +9 -2
  224. package/lib/whois-common-formats.mjs +5 -5
  225. package/lib/whois-contracts.mjs +2 -1
  226. package/lib/whois-dialects.mjs +2 -2
  227. package/lib/whois-normalization.mjs +3 -1
  228. package/lib/whois-parser-support.mjs +8 -1
  229. package/lib/whois-parser.mjs +5 -3
  230. package/lib/whois-transport.mjs +23 -7
  231. package/package.json +14 -14
  232. package/packages/analysis/analyst-taxonomy.mjs +40 -0
  233. package/packages/analysis/bounded-json.mjs +330 -0
  234. package/packages/analysis/candidate-provenance-bounds.mjs +4 -0
  235. package/packages/analysis/cli-argument-grammar.mjs +216 -0
  236. package/packages/analysis/ct-query.mjs +27 -0
  237. package/packages/analysis/ct-response-bounds.mjs +9 -0
  238. package/packages/analysis/external-intelligence-risk.mjs +124 -0
  239. package/packages/analysis/http-evidence-bounds.mjs +8 -0
  240. package/packages/analysis/lookup-network-evidence-bounds.mjs +10 -0
  241. package/packages/analysis/opportunity-scoring.mjs +107 -0
  242. package/packages/analysis/perceptual-hash-comparison.mjs +34 -0
  243. package/packages/analysis/portable-generator.mjs +29 -0
  244. package/packages/analysis/project-metadata.mjs +8 -0
  245. package/packages/analysis/registrable-domain.mjs +56 -0
  246. package/packages/analysis/risk-calibration-summary.mjs +352 -0
  247. package/packages/analysis/risk-scoring.mjs +345 -0
  248. package/packages/analysis/scoring-evidence-quality.mjs +107 -0
  249. package/packages/analysis/semantic-version.mjs +54 -0
  250. package/packages/analysis/threat-intelligence-types.mjs +75 -0
  251. package/packages/cases/case-attachment-model.mjs +83 -0
  252. package/packages/cases/case-evidence-links.mjs +135 -0
  253. package/packages/cases/case-evidence-model.mjs +229 -69
  254. package/packages/cases/case-evidence-quality.mjs +5 -0
  255. package/packages/cases/case-export-input.mjs +55 -0
  256. package/packages/cases/case-incident-context.mjs +52 -0
  257. package/packages/cases/case-markdown.mjs +11 -0
  258. package/packages/cases/case-migration-model.mjs +98 -48
  259. package/packages/cases/case-model.mjs +1 -0
  260. package/packages/cases/case-recheck-model.mjs +149 -0
  261. package/packages/cases/case-record-contracts.mjs +1 -1
  262. package/packages/cases/case-record-core.mjs +4 -3
  263. package/packages/cases/case-record-operations.mjs +123 -133
  264. package/packages/cases/case-record-projection.mjs +30 -20
  265. package/packages/cases/case-record-version-input.mjs +19 -0
  266. package/packages/cases/case-report.mjs +114 -67
  267. package/packages/cases/case-requested-evidence.mjs +146 -0
  268. package/packages/cases/case-response-actions.mjs +756 -0
  269. package/packages/cases/case-response-model.mjs +49 -1129
  270. package/packages/cases/case-response-outcomes.mjs +338 -0
  271. package/packages/cases/case-response-packet-render.mjs +157 -0
  272. package/packages/cases/case-response-packet-types.mjs +1 -0
  273. package/packages/cases/case-response-packet-vocabulary.mjs +48 -0
  274. package/packages/cases/case-response-packet.mjs +58 -593
  275. package/packages/cases/case-response-records.mjs +93 -0
  276. package/packages/cases/case-response-review-inputs.mjs +382 -0
  277. package/packages/cases/case-response-values.mjs +85 -0
  278. package/packages/cases/case-review-package.mjs +45 -0
  279. package/packages/cases/case-selection.mjs +46 -0
  280. package/packages/cases/case-storage-model.mjs +26 -1
  281. package/packages/cases/case-workflow-metadata.mjs +225 -0
  282. package/packages/cases/case-workflow-migration.mjs +43 -0
  283. package/packages/cases/http-summary.mjs +6 -1
  284. package/packages/cases/response-route-freshness.mjs +16 -0
  285. package/packages/comparison/capture-context.mjs +61 -0
  286. package/packages/comparison/comparison-ledger-bulk.mjs +4 -1
  287. package/packages/comparison/favicon-similarity.mjs +1 -1
  288. package/packages/comparison/page-similarity.mjs +3 -2
  289. package/packages/comparison/relationship-evidence.mjs +103 -14
  290. package/packages/comparison/relationship-provenance.mjs +99 -0
  291. package/packages/contracts/analyst-interchange.mjs +234 -0
  292. package/packages/contracts/analyst-review-state-contract.mjs +11 -0
  293. package/packages/contracts/analyst-review-state.mjs +5 -4
  294. package/packages/contracts/case-portability.mjs +370 -114
  295. package/packages/contracts/case-views-contract.mjs +12 -0
  296. package/packages/contracts/case-views.mjs +26 -0
  297. package/packages/contracts/cli-command-semantics.mjs +3 -0
  298. package/packages/contracts/cli-grammar.mjs +6 -0
  299. package/packages/contracts/cli-lookup-brief.mjs +2 -0
  300. package/packages/contracts/cli-lookup.mjs +0 -1
  301. package/packages/contracts/context-review.mjs +24 -0
  302. package/packages/contracts/document-intake.mjs +11 -0
  303. package/packages/contracts/domain-control-flight-recorder.mjs +98 -44
  304. package/packages/contracts/domain-control-manifest.mjs +128 -74
  305. package/packages/contracts/domain-control-monitor.mjs +59 -45
  306. package/packages/contracts/domain-control-review.mjs +200 -121
  307. package/packages/contracts/domain-name.mjs +21 -0
  308. package/packages/contracts/external-observation-interchange.mjs +2 -1
  309. package/packages/contracts/extracted-domain-lifecycle.mjs +11 -32
  310. package/packages/contracts/har-review.mjs +2 -0
  311. package/packages/contracts/http-url.mjs +2 -0
  312. package/packages/contracts/identity-events.mjs +4 -0
  313. package/packages/contracts/investigation-package-limits.mjs +24 -0
  314. package/packages/contracts/investigation-portability.mjs +56 -27
  315. package/packages/contracts/investigation-run.mjs +18 -0
  316. package/packages/contracts/ip-address.mjs +44 -0
  317. package/packages/contracts/lookup-evidence.mjs +35 -0
  318. package/packages/contracts/mail-authentication.mjs +5 -0
  319. package/packages/contracts/message-intake.mjs +31 -0
  320. package/packages/contracts/offline-comparison.mjs +4 -2
  321. package/packages/contracts/page-fingerprints.mjs +15 -0
  322. package/packages/contracts/passive-mail.mjs +10 -0
  323. package/packages/contracts/risk-calibration.mjs +0 -1
  324. package/packages/contracts/schema-compatibility.mjs +1 -1
  325. package/packages/contracts/schema-lifecycle.mjs +83 -153
  326. package/packages/contracts/selected-file-limits.mjs +6 -0
  327. package/packages/contracts/vulnerability-identifiers.mjs +5 -0
  328. package/packages/contracts/web-capture.mjs +10 -0
  329. package/packages/contracts/workspace-portability.mjs +219 -238
  330. package/packages/evidence/artifact-integrity.mjs +8 -2
  331. package/packages/evidence/artifact-structure.mjs +105 -0
  332. package/packages/evidence/collection-quality.mjs +67 -0
  333. package/packages/evidence/decision-fact.mjs +4 -1
  334. package/packages/evidence/dns-query-outcome.mjs +72 -0
  335. package/packages/evidence/domain-control-runtime.mjs +155 -27
  336. package/packages/evidence/domain-posture-context.mjs +79 -0
  337. package/packages/evidence/email-recipient.mjs +18 -0
  338. package/packages/evidence/image-regions.mjs +56 -0
  339. package/packages/evidence/latest-observations.mjs +28 -0
  340. package/packages/evidence/lookup-target.mjs +108 -0
  341. package/packages/evidence/observation.mjs +18 -1
  342. package/packages/evidence/passphrase-encryption.mjs +44 -0
  343. package/packages/evidence/png-pixels.mjs +117 -0
  344. package/packages/evidence/public-address-policy.mjs +83 -0
  345. package/packages/evidence/record-identity.mjs +72 -0
  346. package/packages/evidence/registry-dates.mjs +190 -0
  347. package/packages/evidence/retained-file.mjs +69 -0
  348. package/packages/evidence/review-age.mjs +14 -0
  349. package/packages/interchange/bagit.mjs +342 -0
  350. package/packages/interchange/bounded-zip-extraction.mjs +278 -0
  351. package/packages/interchange/crc32.mjs +17 -0
  352. package/packages/interchange/defensive-indicator-export.mjs +264 -0
  353. package/packages/interchange/external-findings-import.mjs +93 -61
  354. package/packages/interchange/managed-indicator-export.mjs +35 -0
  355. package/packages/interchange/managed-indicator-set.mjs +210 -0
  356. package/packages/interchange/misp-indicator-export.mjs +93 -0
  357. package/packages/interchange/sharing-policy.mjs +56 -0
  358. package/packages/interchange/stix-indicator-export.mjs +129 -0
  359. package/packages/interchange/web-capture-import.mjs +389 -0
  360. package/packages/investigation/acquisition-decision-packet.mjs +1 -1
  361. package/packages/investigation/bulk-mail-exposure.mjs +9 -14
  362. package/packages/investigation/capture-coverage.mjs +57 -0
  363. package/packages/investigation/connector-provenance-review.mjs +100 -0
  364. package/packages/investigation/context-review.mjs +35 -0
  365. package/packages/investigation/document-intake.mjs +81 -0
  366. package/packages/investigation/docx-intake.mjs +133 -0
  367. package/packages/investigation/domain-history-review.mjs +100 -0
  368. package/packages/investigation/domain-transition-review.mjs +47 -0
  369. package/packages/investigation/evidence-coverage-ledger.mjs +9 -1
  370. package/packages/investigation/har-intake.mjs +68 -0
  371. package/packages/investigation/identity-event-intake.mjs +131 -0
  372. package/packages/investigation/identity-incident-review.mjs +39 -0
  373. package/packages/investigation/incident-sequence-review.mjs +58 -0
  374. package/packages/investigation/intake-report.mjs +19 -0
  375. package/packages/investigation/investigation-bagit.mjs +14 -0
  376. package/packages/investigation/investigation-capsule.mjs +33 -5
  377. package/packages/investigation/investigation-manifest.mjs +200 -0
  378. package/packages/investigation/investigation-package-crypto.mjs +98 -0
  379. package/packages/investigation/investigation-package.mjs +200 -0
  380. package/packages/investigation/link-intake.mjs +179 -0
  381. package/packages/investigation/lookup-asset-graph-inputs.mjs +38 -0
  382. package/packages/investigation/lookup-asset-graph.mjs +161 -141
  383. package/packages/investigation/lookup-claim-readiness.mjs +18 -0
  384. package/packages/investigation/lookup-investigation-brief.mjs +3 -3
  385. package/packages/investigation/lookup-task-guidance.mjs +58 -0
  386. package/packages/investigation/mail-authentication-review.mjs +222 -0
  387. package/packages/investigation/mail-header-identity.mjs +209 -0
  388. package/packages/investigation/message-intake.mjs +195 -0
  389. package/packages/investigation/page-behaviour.mjs +113 -0
  390. package/packages/investigation/pdf-intake.mjs +155 -0
  391. package/packages/investigation/platform-continuity-review.mjs +60 -0
  392. package/packages/investigation/qr-intake.mjs +56 -0
  393. package/packages/investigation/requested-action-hints.mjs +11 -0
  394. package/packages/investigation/selected-input-review.mjs +17 -0
  395. package/packages/investigation/storefront-review.mjs +70 -0
  396. package/packages/monitoring/analyst-review-state.mjs +38 -90
  397. package/packages/workspace/brand-profile-model.mjs +160 -22
  398. package/packages/workspace/bulk-columns.mjs +17 -0
  399. package/packages/workspace/bulk-review-model.mjs +39 -31
  400. package/packages/workspace/bulk-session-model.mjs +112 -27
  401. package/packages/workspace/bulk-sort.mjs +1 -0
  402. package/packages/workspace/campaign-model.mjs +1 -1
  403. package/packages/workspace/case-views.mjs +102 -0
  404. package/packages/workspace/detection-rule-model.mjs +1 -1
  405. package/packages/workspace/hostile-input.mjs +29 -8
  406. package/packages/workspace/investigation-guide.mjs +2 -2
  407. package/packages/workspace/investigation-template-model.mjs +45 -6
  408. package/packages/workspace/page-baseline.mjs +20 -17
  409. package/packages/workspace/relationship-observation-model.mjs +54 -35
  410. package/packages/workspace/shortlist-model.mjs +14 -5
  411. package/packages/workspace/watchlist-history.mjs +30 -14
  412. package/packages/workspace/watchlist-store.mjs +24 -6
  413. package/packages/workspace/website-snapshot-model.mjs +98 -33
  414. package/packages/workspace/workspace-archive-crypto.mjs +41 -61
  415. package/packages/workspace/workspace-archive.mjs +90 -25
  416. package/third-party-notices.txt +577 -17
  417. package/lib/hostname.mjs +0 -38
  418. package/packages/investigation/bulk-review-export.mjs +0 -63
@@ -0,0 +1,123 @@
1
+ import {} from "./command-argument-grammar.mjs";
2
+ import {} from "./fail-policy.mjs";
3
+ import { commandDefaultNumber, commandDefaultText } from "./command-reference.mjs";
4
+ import { COLLECTION_COMMAND_DEFINITIONS } from "./collection-command-definitions.mjs";
5
+ import { terminalOptions, normalizedLabel, failPolicies, parseOutput, } from "./argument-values.mjs";
6
+ function parseLookupArguments(parsed) {
7
+ const output = parseOutput(parsed, COLLECTION_COMMAND_DEFINITIONS.lookup);
8
+ const selectedFailPolicies = failPolicies(parsed, 'lookup');
9
+ return {
10
+ action: 'lookup',
11
+ query: parsed.positionalValue('target'),
12
+ output,
13
+ deep: parsed.hasOption('--deep'),
14
+ detail: parsed.hasOption('--summary')
15
+ ? 'summary'
16
+ : parsed.hasOption('--verbose')
17
+ ? 'verbose'
18
+ : 'standard',
19
+ strictExit: parsed.hasOption('--strict-exit'),
20
+ events: parsed.hasOption('--events'),
21
+ plan: parsed.hasOption('--plan'),
22
+ includeAttribution: !parsed.hasOption('--no-attribution'),
23
+ observerLabel: normalizedLabel(parsed, '--observer', 80),
24
+ vantageLabel: normalizedLabel(parsed, '--vantage', 80),
25
+ ...terminalOptions(parsed),
26
+ ...(parsed.hasOption('--browse') ? { browse: true } : {}),
27
+ ...(parsed.hasOption('--exact-url') ? { exactUrl: true } : {}),
28
+ ...(parsed.optionValue('--save-lookup')
29
+ ? { saveLookup: parsed.optionValue('--save-lookup') }
30
+ : {}),
31
+ ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
32
+ };
33
+ }
34
+ function parseBulkArguments(parsed) {
35
+ const deep = parsed.hasOption('--deep');
36
+ const selectedFailPolicies = failPolicies(parsed, 'bulk');
37
+ const output = parseOutput(parsed, COLLECTION_COMMAND_DEFINITIONS.bulk);
38
+ const filter = parsed.hasOption('--registered-only')
39
+ ? 'registered'
40
+ : parsed.hasOption('--inconclusive-only')
41
+ ? 'inconclusive'
42
+ : parsed.hasOption('--errors-only')
43
+ ? 'errors'
44
+ : 'all';
45
+ return {
46
+ action: 'bulk',
47
+ source: parsed.positionalValue('source'),
48
+ output,
49
+ deep,
50
+ concurrency: parsed.integerOption('--concurrency') ?? commandDefaultNumber('bulk', '--concurrency', deep),
51
+ checkpoint: parsed.optionValue('--checkpoint'),
52
+ resume: parsed.hasOption('--resume'),
53
+ events: parsed.hasOption('--events'),
54
+ plan: parsed.hasOption('--plan'),
55
+ filter,
56
+ ...terminalOptions(parsed),
57
+ ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
58
+ };
59
+ }
60
+ function parseDiscoverArguments(parsed) {
61
+ return {
62
+ action: 'discover',
63
+ seed: parsed.positionalValue('subject'),
64
+ output: parseOutput(parsed, COLLECTION_COMMAND_DEFINITIONS.discover),
65
+ ...discoveryValues(parsed),
66
+ snapshotSource: parsed.optionValue('--snapshot'),
67
+ ...terminalOptions(parsed),
68
+ };
69
+ }
70
+ function discoveryValues(parsed) {
71
+ const familyText = parsed.optionValue('--families');
72
+ return {
73
+ preset: (familyText
74
+ ? 'custom'
75
+ : (parsed.optionValue('--preset') ?? commandDefaultText('discover', '--preset'))),
76
+ keyboardLayout: (parsed.optionValue('--keyboard') ??
77
+ commandDefaultText('discover', '--keyboard')),
78
+ tldText: parsed.optionValue('--tlds'),
79
+ dictionarySource: parsed.optionValue('--dictionary'),
80
+ familyText,
81
+ };
82
+ }
83
+ function parseDiscoverScanArguments(parsed) {
84
+ const deep = parsed.hasOption('--deep');
85
+ const selectedFailPolicies = failPolicies(parsed, 'discover-scan');
86
+ const filter = parsed.hasOption('--registered-only')
87
+ ? 'registered'
88
+ : parsed.hasOption('--inconclusive-only')
89
+ ? 'inconclusive'
90
+ : parsed.hasOption('--acquisition-only')
91
+ ? 'acquisition'
92
+ : parsed.hasOption('--suppressed-only')
93
+ ? 'suppressed'
94
+ : 'all';
95
+ return {
96
+ action: 'discover-scan',
97
+ seed: parsed.positionalValue('subject'),
98
+ output: parseOutput(parsed, COLLECTION_COMMAND_DEFINITIONS['discover-scan']),
99
+ ...discoveryValues(parsed),
100
+ deep,
101
+ scanLimit: parsed.integerOption('--scan-limit') ??
102
+ commandDefaultNumber('discover-scan', '--scan-limit', deep),
103
+ chunkSize: parsed.integerOption('--chunk-size') ?? commandDefaultNumber('discover-scan', '--chunk-size'),
104
+ concurrency: parsed.integerOption('--concurrency') ??
105
+ commandDefaultNumber('discover-scan', '--concurrency', deep),
106
+ checkpoint: parsed.optionValue('--checkpoint'),
107
+ resume: parsed.hasOption('--resume'),
108
+ resolverText: parsed.optionValue('--resolver'),
109
+ observationSnapshot: parsed.optionValue('--observation-snapshot'),
110
+ allowlistSource: parsed.optionValue('--allowlist'),
111
+ filter,
112
+ events: parsed.hasOption('--events'),
113
+ plan: parsed.hasOption('--plan'),
114
+ ...terminalOptions(parsed),
115
+ ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
116
+ };
117
+ }
118
+ export const COLLECTION_ARGUMENT_PARSERS = Object.freeze({
119
+ lookup: parseLookupArguments,
120
+ bulk: parseBulkArguments,
121
+ discover: parseDiscoverArguments,
122
+ 'discover-scan': parseDiscoverScanArguments,
123
+ });
@@ -0,0 +1,330 @@
1
+ import { positional, OPTIONAL_FILE_POSITIONAL, OPTIONAL_TEXT_POSITIONAL, constraint, commandSeed, } from "./command-definition.mjs";
2
+ import { bulkQueryLimit, bulkConcurrencyLimit } from "../lib/bulk-limits.mjs";
3
+ const COLLECTION_CEILINGS = `${bulkQueryLimit('fast')} fast or ${bulkQueryLimit('deep')} deep`;
4
+ const CONCURRENCY_CEILINGS = `${bulkConcurrencyLimit('fast')} fast or ${bulkConcurrencyLimit('deep')} deep`;
5
+ export const COLLECTION_COMMAND_DEFINITIONS = Object.freeze({
6
+ lookup: commandSeed({
7
+ reference: {
8
+ description: 'Collect registration evidence for one domain, IP, or ASN.',
9
+ example: 'whoisleuth lookup example.test --deep --browse',
10
+ boundary: 'Fast is the default. An ICANN-recognised public domain, reserved documentation domain, IP, or ASN may occupy command position as shorthand; it delegates to this same parser and URL-like input requires the explicit lookup command. Deep mode adds bounded WHOIS, DNS, HTTP, TLS, technology, posture, and network context where applicable. --deep --exact-url explicitly sends the input URL path and query to the website, without its fragment; ordinary URL input sends only the hostname. --plan remains offline and omits the selected URL. Retained paths and page-derived text require review before sharing. A full Deep homepage observation can derive fixed publication and delivery/cache summaries from the same response without retaining raw metadata values or making another request. --browse opens before collection, shows aggregate Fast progress or independently settled planned Deep sources, and then navigates allowlisted retained fields in the completed document. Press ? for help and / to search rendered panel text only. Closing during collection cancels without a partial document. --save-lookup writes the exact completed private JSON only after a normal browser close; it can contain normalised evidence omitted from panels and refuses an existing path.',
11
+ },
12
+ collection: {
13
+ scope: 'Accepts one target. Fast is the default; deep collection must be selected explicitly.',
14
+ },
15
+ summary: 'Collect one domain, IP, or ASN',
16
+ options: [
17
+ '--json',
18
+ '--junit',
19
+ '--markdown',
20
+ '--html',
21
+ '--no-attribution',
22
+ '--fast',
23
+ '--deep',
24
+ '--exact-url',
25
+ '--observer',
26
+ '--vantage',
27
+ '--plan',
28
+ '--summary',
29
+ '--verbose',
30
+ '--browse',
31
+ '--save-lookup',
32
+ '--strict-exit',
33
+ '--fail-on',
34
+ '--events',
35
+ '--quiet',
36
+ '--no-color',
37
+ ],
38
+ positionals: Object.freeze([
39
+ positional('target', 'text', 0, 1, [], 'argv_or_stdin', ['--browse']),
40
+ ]),
41
+ constraints: Object.freeze([
42
+ constraint({
43
+ kind: 'mutually_exclusive',
44
+ options: ['--json', '--junit', '--markdown', '--html'],
45
+ }),
46
+ constraint({ kind: 'mutually_exclusive', options: ['--fast', '--deep'] }),
47
+ constraint({ kind: 'mutually_exclusive', options: ['--summary', '--verbose'] }),
48
+ constraint({ kind: 'requires_all', option: '--save-lookup', requiredOptions: ['--browse'] }),
49
+ constraint({ kind: 'requires_all', option: '--exact-url', requiredOptions: ['--deep'] }),
50
+ constraint({
51
+ kind: 'excludes_all',
52
+ option: '--summary',
53
+ excludedOptions: ['--json', '--junit', '--markdown', '--html'],
54
+ }),
55
+ constraint({
56
+ kind: 'excludes_all',
57
+ option: '--verbose',
58
+ excludedOptions: ['--json', '--junit', '--markdown', '--html'],
59
+ }),
60
+ constraint({
61
+ kind: 'excludes_all',
62
+ option: '--browse',
63
+ excludedOptions: [
64
+ '--json',
65
+ '--junit',
66
+ '--markdown',
67
+ '--html',
68
+ '--summary',
69
+ '--verbose',
70
+ '--events',
71
+ '--plan',
72
+ '--quiet',
73
+ ],
74
+ }),
75
+ constraint({
76
+ kind: 'requires_any',
77
+ option: '--no-attribution',
78
+ requiredOptions: ['--markdown', '--html'],
79
+ }),
80
+ constraint({
81
+ kind: 'excludes_all',
82
+ option: '--plan',
83
+ excludedOptions: [
84
+ '--junit',
85
+ '--markdown',
86
+ '--html',
87
+ '--summary',
88
+ '--verbose',
89
+ '--strict-exit',
90
+ '--events',
91
+ '--quiet',
92
+ '--fail-on',
93
+ ],
94
+ }),
95
+ ]),
96
+ handlerOwner: 'lookup',
97
+ networkEffect: 'conditional_network',
98
+ common: true,
99
+ schemaIdentifiers: Object.freeze(['whoisleuth.cli.lookup', 'whoisleuth.cli.lookup-plan']),
100
+ primaryArtefacts: Object.freeze(['Source-qualified Lookup', 'Lookup request plan']),
101
+ planSupport: true,
102
+ additionalOutputFormats: Object.freeze([]),
103
+ bootstrapProfile: 'allowed',
104
+ }),
105
+ bulk: commandSeed({
106
+ reference: {
107
+ description: 'Triage newline-delimited domains, IPs, or ASNs with bounded concurrency.',
108
+ example: 'cat domains.txt | whoisleuth bulk --jsonl',
109
+ boundary: 'Fast and deep jobs use separate concurrency ceilings. Filters affect output only; collection failures and inconclusive authority states remain explicit in JSON, JSONL, and CSV. --csv-with-metadata adds source versions, separate observation and report times, collection origin and diagnostic states; --csv retains the compact columns.',
110
+ },
111
+ collection: {
112
+ scope: `Accepts at most ${COLLECTION_CEILINGS} targets, with concurrency capped at ${CONCURRENCY_CEILINGS}.`,
113
+ },
114
+ summary: 'Run bounded multi-target collection',
115
+ options: [
116
+ '--json',
117
+ '--jsonl',
118
+ '--junit',
119
+ '--csv',
120
+ '--csv-with-metadata',
121
+ '--domains',
122
+ '--queries',
123
+ '--registered-only',
124
+ '--inconclusive-only',
125
+ '--errors-only',
126
+ '--fast',
127
+ '--deep',
128
+ '--concurrency',
129
+ '--checkpoint',
130
+ '--resume',
131
+ '--events',
132
+ '--plan',
133
+ '--fail-on',
134
+ '--quiet',
135
+ '--no-color',
136
+ ],
137
+ positionals: OPTIONAL_FILE_POSITIONAL,
138
+ constraints: Object.freeze([
139
+ constraint({
140
+ kind: 'mutually_exclusive',
141
+ options: [
142
+ '--json',
143
+ '--jsonl',
144
+ '--junit',
145
+ '--csv',
146
+ '--csv-with-metadata',
147
+ '--domains',
148
+ '--queries',
149
+ ],
150
+ }),
151
+ constraint({
152
+ kind: 'mutually_exclusive',
153
+ options: ['--registered-only', '--inconclusive-only', '--errors-only'],
154
+ }),
155
+ constraint({ kind: 'mutually_exclusive', options: ['--fast', '--deep'] }),
156
+ constraint({ kind: 'requires_all', option: '--resume', requiredOptions: ['--checkpoint'] }),
157
+ constraint({
158
+ kind: 'excludes_all',
159
+ option: '--plan',
160
+ excludedOptions: [
161
+ '--jsonl',
162
+ '--junit',
163
+ '--csv',
164
+ '--csv-with-metadata',
165
+ '--domains',
166
+ '--queries',
167
+ '--events',
168
+ '--checkpoint',
169
+ '--resume',
170
+ '--quiet',
171
+ '--fail-on',
172
+ ],
173
+ }),
174
+ ]),
175
+ handlerOwner: 'bulk',
176
+ networkEffect: 'conditional_network',
177
+ common: true,
178
+ schemaIdentifiers: Object.freeze([
179
+ 'whoisleuth.cli.bulk',
180
+ 'whoisleuth.cli.bulk.item',
181
+ 'whoisleuth.cli.bulk-checkpoint',
182
+ ]),
183
+ primaryArtefacts: Object.freeze(['Bulk result', 'Bulk checkpoint']),
184
+ planSupport: true,
185
+ additionalOutputFormats: Object.freeze([]),
186
+ bootstrapProfile: 'allowed',
187
+ }),
188
+ discover: commandSeed({
189
+ reference: {
190
+ description: 'Generate bounded lookalike-domain candidates from a brand or registrable domain, including multi-part public suffixes.',
191
+ example: 'whoisleuth discover example.test --preset common --jsonl',
192
+ boundary: 'Generation and optional local snapshot comparison are offline. Candidates are leads only and are not resolved, registered, or classified as malicious.',
193
+ },
194
+ collection: {
195
+ scope: 'Generates a bounded candidate set from local rules, dictionaries, and optional saved snapshots.',
196
+ },
197
+ summary: 'Generate lookalike candidates offline',
198
+ options: [
199
+ '--tlds',
200
+ '--preset',
201
+ '--families',
202
+ '--keyboard',
203
+ '--dictionary',
204
+ '--snapshot',
205
+ '--json',
206
+ '--jsonl',
207
+ '--domains',
208
+ '--quiet',
209
+ '--no-color',
210
+ ],
211
+ positionals: OPTIONAL_TEXT_POSITIONAL,
212
+ constraints: Object.freeze([
213
+ constraint({ kind: 'mutually_exclusive', options: ['--json', '--jsonl', '--domains'] }),
214
+ constraint({ kind: 'mutually_exclusive', options: ['--preset', '--families'] }),
215
+ constraint({
216
+ kind: 'value_excludes',
217
+ option: '--preset',
218
+ value: 'common',
219
+ excludedOptions: ['--dictionary'],
220
+ }),
221
+ ]),
222
+ handlerOwner: 'discovery',
223
+ networkEffect: 'offline',
224
+ common: true,
225
+ schemaIdentifiers: Object.freeze([
226
+ 'whoisleuth.cli.discover',
227
+ 'whoisleuth.cli.discover.item',
228
+ 'whoisleuth.cli.discovery-snapshot',
229
+ ]),
230
+ primaryArtefacts: Object.freeze(['Candidate set', 'Discovery snapshot']),
231
+ planSupport: false,
232
+ additionalOutputFormats: Object.freeze([]),
233
+ bootstrapProfile: 'allowed',
234
+ }),
235
+ 'discover-scan': commandSeed({
236
+ reference: {
237
+ description: 'Generate a bounded candidate set, collect a selected subset, and produce a supervised review queue.',
238
+ example: 'whoisleuth discover-scan example.test --scan-limit 50 --checkpoint scan.json --json',
239
+ boundary: `This command performs network collection. Fast compact lookup is the default; deep mode is capped at ${bulkQueryLimit('deep')} candidates. Allowlisting changes review priority only and shared infrastructure remains a lead, not attribution. --csv-with-metadata adds source versions, separate observation and report times, collection origin and diagnostic states; --csv retains the compact columns.`,
240
+ },
241
+ collection: {
242
+ scope: `Scans at most ${COLLECTION_CEILINGS} candidates, with concurrency capped at ${CONCURRENCY_CEILINGS}.`,
243
+ },
244
+ summary: 'Collect a supervised candidate review queue',
245
+ options: [
246
+ '--tlds',
247
+ '--preset',
248
+ '--families',
249
+ '--keyboard',
250
+ '--dictionary',
251
+ '--fast',
252
+ '--deep',
253
+ '--scan-limit',
254
+ '--chunk-size',
255
+ '--concurrency',
256
+ '--resolver',
257
+ '--allowlist',
258
+ '--checkpoint',
259
+ '--resume',
260
+ '--observation-snapshot',
261
+ '--registered-only',
262
+ '--inconclusive-only',
263
+ '--acquisition-only',
264
+ '--suppressed-only',
265
+ '--events',
266
+ '--plan',
267
+ '--fail-on',
268
+ '--json',
269
+ '--jsonl',
270
+ '--csv',
271
+ '--csv-with-metadata',
272
+ '--domains',
273
+ '--quiet',
274
+ '--no-color',
275
+ ],
276
+ positionals: OPTIONAL_TEXT_POSITIONAL,
277
+ constraints: Object.freeze([
278
+ constraint({
279
+ kind: 'mutually_exclusive',
280
+ options: ['--json', '--jsonl', '--csv', '--csv-with-metadata', '--domains'],
281
+ }),
282
+ constraint({ kind: 'mutually_exclusive', options: ['--preset', '--families'] }),
283
+ constraint({ kind: 'mutually_exclusive', options: ['--fast', '--deep'] }),
284
+ constraint({
285
+ kind: 'mutually_exclusive',
286
+ options: [
287
+ '--registered-only',
288
+ '--inconclusive-only',
289
+ '--acquisition-only',
290
+ '--suppressed-only',
291
+ ],
292
+ }),
293
+ constraint({ kind: 'requires_all', option: '--resume', requiredOptions: ['--checkpoint'] }),
294
+ constraint({
295
+ kind: 'value_excludes',
296
+ option: '--preset',
297
+ value: 'common',
298
+ excludedOptions: ['--dictionary'],
299
+ }),
300
+ constraint({
301
+ kind: 'excludes_all',
302
+ option: '--plan',
303
+ excludedOptions: [
304
+ '--jsonl',
305
+ '--csv',
306
+ '--csv-with-metadata',
307
+ '--domains',
308
+ '--events',
309
+ '--checkpoint',
310
+ '--resume',
311
+ '--observation-snapshot',
312
+ '--quiet',
313
+ '--fail-on',
314
+ ],
315
+ }),
316
+ ]),
317
+ handlerOwner: 'discovery_scan',
318
+ networkEffect: 'conditional_network',
319
+ common: true,
320
+ schemaIdentifiers: Object.freeze([
321
+ 'whoisleuth.cli.discovery-scan',
322
+ 'whoisleuth.cli.discovery-scan.item',
323
+ 'whoisleuth.cli.discovery-observation-snapshot',
324
+ ]),
325
+ primaryArtefacts: Object.freeze(['Reviewed candidate queue', 'Observation snapshot']),
326
+ planSupport: true,
327
+ additionalOutputFormats: Object.freeze([]),
328
+ bootstrapProfile: 'allowed',
329
+ }),
330
+ });
@@ -1,3 +1,4 @@
1
+ import { bulkQueryLimit } from "../lib/bulk-limits.mjs";
1
2
  export const CLI_COLLECTION_PREFLIGHT_SCHEMA = 'whoisleuth.cli.collection-preflight';
2
3
  export const CLI_COLLECTION_PREFLIGHT_VERSION = 1;
3
4
  export function buildCollectionPreflight(options) {
@@ -12,7 +13,7 @@ export function buildCollectionPreflight(options) {
12
13
  networkRequestsMade: false,
13
14
  scope: Object.freeze({
14
15
  selectedTargets: options.targetCount,
15
- commandTargetLimit: options.targetLimit,
16
+ commandTargetLimit: bulkQueryLimit(options.deep ? 'deep' : 'fast'),
16
17
  concurrency: options.concurrency,
17
18
  sourceFamilies: Object.freeze(sourceFamilies),
18
19
  exactRequestCountKnown: false,
@@ -53,6 +54,12 @@ export function formatCollectionPreflight(document) {
53
54
  ...document.scope.sourceFamilies.map((source) => ` ${source}`),
54
55
  '',
55
56
  ...document.disclosure.map((item) => `Disclosure: ${item}`),
57
+ '',
58
+ `Output format: ${document.persistence.output}`,
59
+ `Checkpoint: ${document.persistence.checkpoint ? 'enabled' : 'not written'}. ${document.persistence.note}`,
60
+ ...(document.review.allowlistAffectsPriorityOnly ? ['Allowlist: affects review priority only; it does not exclude targets from collection.'] : []),
61
+ 'Enforcement: none. This plan does not report, block or remove a target.',
62
+ '',
56
63
  ...document.limitations.map((item) => `Limitation: ${item}`),
57
64
  '',
58
65
  ].join('\n');