@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
@@ -1,15 +1,39 @@
1
1
  import { formatCliJunit } from "./ci-report.mjs";
2
2
  import { formatDomainControlMonitor, runDomainControlMonitor } from "./domain-control-monitor.mjs";
3
- import { boundedCliErrorMessage, CliUsageError } from "./errors.mjs";
3
+ import { boundedCliErrorMessage, createCliDiagnosticOutput, CliUsageError } from "./errors.mjs";
4
4
  import EXIT_CODES from "./exit-codes.mjs";
5
5
  import { evaluateCliFailPolicies, formatFailPolicyNotice } from "./fail-policy.mjs";
6
6
  import { formatJsonDocument } from "./formatters/json.mjs";
7
7
  import { buildInvestigationPlan, buildWorkflowRecipeCatalogue, formatInvestigationPlan, formatWorkflowRecipeCatalogue, } from "./investigation-plan.mjs";
8
- import { MAX_INVESTIGATION_RUN_BYTES, formatInvestigationRun, runInvestigationRecipe, } from "./investigation-run.mjs";
8
+ import { MAX_INVESTIGATION_RUN_BYTES, formatInvestigationRun, investigationRunExitCode, runInvestigationRecipe, previewInvestigationRecipe, formatInvestigationPreview, } from "./investigation-run.mjs";
9
9
  import { MAX_OFFLINE_EVIDENCE_INPUT_BYTES } from "./offline-evidence-review.mjs";
10
+ import { MAX_OFFLINE_ARTIFACT_BYTES } from "./artifact-verify.mjs";
11
+ import { MAX_RETAINED_ARTIFACT_DIFF_BYTES } from "./retained-artifact-diff.mjs";
12
+ import { MAX_SAVED_LOOKUP_INPUT_BYTES } from "./saved-lookup.mjs";
13
+ import { MAX_COMPARE_INPUT_BYTES } from "./compare.mjs";
14
+ import { MAX_SOURCE_RELIABILITY_INPUT_BYTES } from "./source-reliability.mjs";
15
+ import { MAX_SHARING_REVIEW_BYTES } from "./sharing-review.mjs";
10
16
  import { createBufferedOutput } from "./output-file.mjs";
17
+ import { boundedInteractiveAnswer, canReadInteractiveLine, readBoundedInteractiveLine } from "./terminal-input.mjs";
11
18
  import { WORKFLOW_INLINE_COMMANDS } from "./inline-command-families.mjs";
12
19
  import { runDiscriminatedCommandHandler } from "./discriminated-command-handlers.mjs";
20
+ function boundWorkflowInputs(command, inputs, dependencies, context) {
21
+ if (!inputs.size)
22
+ return {};
23
+ const read = (source, fallback, maximumBytes, label) => typeof source === 'string' && inputs.has(source)
24
+ ? inputs.get(source)
25
+ : fallback ? fallback(source) : context.readInput(source, maximumBytes, label);
26
+ switch (command) {
27
+ case 'export': return { readExportInput: (source) => read(source, dependencies.readExportInput, MAX_SAVED_LOOKUP_INPUT_BYTES, 'Evidence export input') };
28
+ case 'verify-artifact': return { readArtifactInput: (source) => read(source, dependencies.readArtifactInput, MAX_OFFLINE_ARTIFACT_BYTES, 'Artefact input') };
29
+ case 'sharing-review': return { readArtifactInput: (source) => read(source, dependencies.readArtifactInput, MAX_SHARING_REVIEW_BYTES, 'Sharing review input') };
30
+ case 'compare': return { readCompareInput: (source) => read(source, dependencies.readCompareInput, MAX_COMPARE_INPUT_BYTES, 'Comparison input') };
31
+ case 'source-report': return { readSourceReliabilityInput: (source) => read(source, dependencies.readSourceReliabilityInput, MAX_SOURCE_RELIABILITY_INPUT_BYTES, 'Source reliability input') };
32
+ case 'diff':
33
+ case 'timeline': return { readDiffInput: (source) => read(source, dependencies.readDiffInput, command === 'diff' ? MAX_RETAINED_ARTIFACT_DIFF_BYTES : MAX_SAVED_LOOKUP_INPUT_BYTES, command === 'diff' ? 'Retained diff input' : 'Lookup timeline input') };
34
+ default: throw new CliUsageError('This fixed-workflow command does not accept retained artefacts.');
35
+ }
36
+ }
13
37
  async function runMonitorOnceCommand(args, dependencies, context) {
14
38
  context.setFailureLabel('One-shot domain control review');
15
39
  let manifestInput;
@@ -82,12 +106,18 @@ async function runWorkflowPlanCommand(args, dependencies, context) {
82
106
  }
83
107
  async function runWorkflowRecipeCommand(args, dependencies, context) {
84
108
  context.setFailureLabel('Investigation workflow');
109
+ const input = (dependencies.stdin ?? process.stdin);
110
+ if (args.interactive && !canReadInteractiveLine(input, context.stderr, dependencies.environment)) {
111
+ throw new CliUsageError('--interactive requires terminal input and terminal stderr. Use --select for unattended workflows.');
112
+ }
85
113
  let resumeInput = null;
86
114
  if (args.resumeSource) {
87
115
  try {
88
- resumeInput = dependencies.readDiffInput
89
- ? await dependencies.readDiffInput(args.resumeSource)
90
- : await context.readInput(args.resumeSource, MAX_INVESTIGATION_RUN_BYTES, 'Investigation resume state');
116
+ resumeInput = dependencies.workflowResumeInput !== undefined
117
+ ? dependencies.workflowResumeInput
118
+ : dependencies.readDiffInput
119
+ ? await dependencies.readDiffInput(args.resumeSource)
120
+ : await context.readInput(args.resumeSource, MAX_INVESTIGATION_RUN_BYTES, 'Investigation resume state');
91
121
  }
92
122
  catch (error) {
93
123
  if (error instanceof CliUsageError)
@@ -95,20 +125,52 @@ async function runWorkflowRecipeCommand(args, dependencies, context) {
95
125
  throw new CliUsageError(`Could not read investigation resume state: ${boundedCliErrorMessage(error, 'Input could not be read')}`);
96
126
  }
97
127
  }
128
+ if (args.preview) {
129
+ const preview = previewInvestigationRecipe(args.recipe, args.subject, {
130
+ resumeInput, selections: args.selections, artifactBindings: args.artifactBindings, generatedAt: context.now(),
131
+ });
132
+ context.writeStdout(args.output === 'json' ? formatJsonDocument(preview) : context.terminal(formatInvestigationPreview(preview), args.color));
133
+ return EXIT_CODES.SUCCESS;
134
+ }
98
135
  const document = await runInvestigationRecipe(args.recipe, args.subject, {
99
136
  approveNetwork: args.approveNetwork,
100
137
  selections: args.selections,
138
+ artifactBindings: args.artifactBindings,
139
+ confirmedReviews: args.confirmedReviews,
140
+ ...(args.interactive ? { selectInputs: async (request) => {
141
+ context.writeStderr(`${request.label}\nEnter literal input paths or values. Leave blank to pause; no approval is implied.\n`);
142
+ const answers = [];
143
+ for (const placeholder of request.inputs) {
144
+ const prompt = `${request.stepId} ${placeholder}: `;
145
+ const answer = boundedInteractiveAnswer(await (dependencies.workflowQuestion
146
+ ? dependencies.workflowQuestion(prompt)
147
+ : readBoundedInteractiveLine(prompt, { input: input, output: context.stderr,
148
+ ...(dependencies.signal ? { signal: dependencies.signal } : {}) })));
149
+ if (!answer)
150
+ break;
151
+ answers.push(answer);
152
+ }
153
+ return answers;
154
+ } } : {}),
101
155
  resumeInput,
102
156
  generatedAt: context.now(),
103
157
  ...(dependencies.signal ? { signal: dependencies.signal } : {}),
104
- execute: async (command, stepArguments) => {
158
+ execute: async (command, stepArguments, inputs) => {
105
159
  const stepStdout = createBufferedOutput();
106
- const stepStderr = createBufferedOutput();
107
- const exitCode = await context.executeCli([command, ...stepArguments], {
108
- stdout: stepStdout.stream,
109
- stderr: stepStderr.stream,
110
- });
111
- return { exitCode, stdout: stepStdout.value() };
160
+ const stepStderr = createCliDiagnosticOutput();
161
+ try {
162
+ const exitCode = await context.executeCli([command, ...stepArguments], {
163
+ stdout: stepStdout.stream,
164
+ stderr: stepStderr.stream,
165
+ ...boundWorkflowInputs(command, inputs, dependencies, context),
166
+ });
167
+ return { exitCode, stdout: stepStdout.value() };
168
+ }
169
+ finally {
170
+ const diagnostic = stepStderr.value();
171
+ if (diagnostic)
172
+ context.writeStderr(`${command}: ${diagnostic}\n`);
173
+ }
112
174
  },
113
175
  });
114
176
  if (!args.quiet) {
@@ -116,7 +178,7 @@ async function runWorkflowRecipeCommand(args, dependencies, context) {
116
178
  ? formatJsonDocument(document)
117
179
  : context.terminal(formatInvestigationRun(document), args.color));
118
180
  }
119
- return document.state === 'step_failed' ? EXIT_CODES.PARTIAL_FAILURE : EXIT_CODES.SUCCESS;
181
+ return investigationRunExitCode(document);
120
182
  }
121
183
  const WORKFLOW_COMMAND_HANDLERS = Object.freeze({
122
184
  'monitor-once': runMonitorOnceCommand,
@@ -10,22 +10,15 @@ This page records the common interfaces and the boundaries that matter across
10
10
  commands. The generated [privacy/data-flow catalogue](https://github.com/slicedearth/whoisleuth/blob/main/docs/privacy-data-flow-catalogue.md)
11
11
  contains the exhaustive recipient, retention and export metadata.
12
12
 
13
- ## Installation
14
-
15
- Public releases require Node.js 24 or later. Release verification uses the
16
- exact Node.js 24 maintainer runtime and separately exercises the installed
17
- package on Node.js 26:
13
+ For an explicitly selected local IP-location database, see the
14
+ [MMDB query and compatibility guide](cli.md#local-ip-location-database-review).
15
+ Current reviews retain exact-byte identity and intrinsic metadata, and require
16
+ an analyst-justified freshness policy. No database is downloaded or updated.
18
17
 
19
- ```bash
20
- npm exec --yes --ignore-scripts --package=@slicedearth/whoisleuth-cli -- whoisleuth --help
21
- npm install --global --ignore-scripts @slicedearth/whoisleuth-cli
22
- whoisleuth doctor
23
- ```
18
+ ## Installation
24
19
 
25
- The scoped package and application share one semantic version. The package
26
- requires no dependency lifecycle scripts and does not call the hosted
27
- WHOISleuth deployment. From a repository checkout, replace `whoisleuth` with
28
- `node bin/whoisleuth.mts`.
20
+ Use the [installation guide](cli.md#installation) for runtime requirements,
21
+ installation and updates. The CLI runs locally without a hosted account.
29
22
 
30
23
  ## Find and inspect commands
31
24
 
@@ -46,6 +39,13 @@ command position as Lookup shorthand. Use explicit `lookup` where input needs
46
39
  supported URL-like normalisation. Credentials, paths, queries, fragments, ports
47
40
  and unsupported special-use targets are rejected by the shorthand.
48
41
 
42
+ Explicit `lookup` normally uses only a pasted URL's hostname. Add
43
+ `--deep --exact-url` to collect that page's path and query instead of the
44
+ homepage; fragments are not sent. `--plan` discloses this scope without making
45
+ requests or copying the URL into the plan. Use stdin to keep a sensitive URL
46
+ out of shell history. Saved request provenance omits queries, but paths and
47
+ page-derived text still require review before sharing.
48
+
49
49
  `registry-scaffold` has a separate fixture contract: its `--profile` selects one
50
50
  fixed fixture profile and shared `--config` profiles are rejected. It produces
51
51
  sanitised local fixture material and makes no registry request.
@@ -63,12 +63,28 @@ disclosures without collecting. Fast is the Lookup default. Deep adds the
63
63
  applicable registration, DNS, HTTP, TLS, page, technology and network context.
64
64
  Optional browser providers are not implicit CLI actions.
65
65
 
66
- `mail-headers` is an offline review of one analyst-selected RFC-style header
67
- block. It reports domain-only identity, header-reported authentication,
68
- exact-domain alignment, and bounded `Received` routing. It retains no address
69
- local parts, display names, subject, body, attachment, or raw header value in
70
- its output. It does not independently validate SPF, DKIM, DMARC, or ARC and
71
- does not treat divergence as proof of abuse.
66
+ The [message-header review](cli.md#message-header-review) is offline and reports
67
+ publisher claims, not independent DNS or cryptographic validation.
68
+
69
+ For copied-content or credential-abuse review, keep the supplied reference,
70
+ candidate, form destination and deliberately observed navigation separately
71
+ attributed. A similar page without a logo or brand name can still merit manual
72
+ evidence review; correspondence does not establish authorship, rights authority
73
+ or maliciousness. Missing optional capture or comparison evidence does not
74
+ prevent ordinary Case pins and conclusions. Installed command help remains the
75
+ authority for offline file inputs and explicit collection plans.
76
+
77
+ The [reporting guide](https://www.whoisleuth.com/resources/reporting-and-takedown-guidance)
78
+ uses the same reviewed official-route catalogue as the Console for social
79
+ content, storefronts, app listings, hosted files/forms and advertising. Verify
80
+ the exact object, current route, reporter authority and disclosure before any
81
+ manual submission. Fraud, order complaints and rights notices are different
82
+ processes; search or app delisting is not source-content removal. Formal domain
83
+ disputes and copyright procedures have their own criteria, remedies and
84
+ jurisdiction-specific rules, not a universal waiting period. CLI preparation
85
+ does not submit a report or make a legal declaration. Preserve original delivery
86
+ references when preparing additional evidence, and recheck each response scope
87
+ independently rather than treating a closed ticket as remediation.
72
88
 
73
89
  `dnssec-validate` and `mail-transport` are isolated authorised actions. Both
74
90
  require a selected literal public resolver, a local trust-anchor document and
@@ -77,6 +93,8 @@ transport handles at most three selected MX hosts sequentially, sends `EHLO`
77
93
  and uses `STARTTLS` only when advertised. It does not send mail, authenticate,
78
94
  test relay, enumerate recipients or retry automatically. DNSSEC, TLSA/DANE,
79
95
  PKIX, STARTTLS and SMTP transport remain separate evidence states.
96
+ STARTTLS detection uses the full bounded reply. If the retained capability
97
+ inventory is shortened, the report remains partial and names the omission.
80
98
 
81
99
  The repository-only rendered-capture package is outside hosted and distributable
82
100
  collection. It executes remote page JavaScript only for an explicitly
@@ -91,11 +109,20 @@ refused. Output goes to the terminal unless a command supports `--output`.
91
109
  Private output is written atomically and an existing path is refused unless
92
110
  replacement is explicit.
93
111
 
112
+ `--` ends option processing. All later arguments are literal positional inputs,
113
+ including names such as `--help`. Use `./-evidence.json` for a hyphen-prefixed
114
+ filename when completing paths across shells. Options must precede `--`.
115
+
94
116
  Terminal text is the default. JSON, JSONL, CSV, Markdown, HTML and domain-only
95
117
  formats are available only where the installed command declares them.
96
118
  Redirected and machine output contains no ANSI or progress text. Diagnostics
97
119
  and optional target-free `--events` output use standard error.
98
120
 
121
+ For `bulk` and `discover-scan`, `--csv-with-metadata` adds the source schema and
122
+ version, observation and report times, collection origin, scan mode, diagnostic
123
+ version and source-health states. Missing clocks remain `unknown`; a null
124
+ source state is unmeasured, not a negative result. `--csv` keeps the compact columns.
125
+
99
126
  `--fail-on` and `--strict-exit` expose selected evidence states to automation
100
127
  without changing the result document. Review focused help for the policies a
101
128
  command supports.
@@ -116,16 +143,18 @@ Readers accept only their declared public and current versions. Unknown,
116
143
  unreleased historical and future schemas fail before partial interpretation;
117
144
  an invalid import is not treated as an empty document.
118
145
 
119
- `inspect-archive` reads current workspace archive v8 and exact versions 5, 6 and 7. It
146
+ `inspect-archive` reads current workspace archive v9 and exact versions 5–8. It
120
147
  reports section metadata and digest-only search results unless `--reveal` is
121
148
  explicitly selected. It never searches notes, contacts or arbitrary raw fields.
122
149
 
123
150
  `export` reads supported saved Lookup v1 or v2 and writes current Lookup
124
- evidence schema 28. Published v2 schema 27 and exact v1 schema 26 remain
125
- readable. Versions 27 and 28 exclude raw registration payloads, expanded
151
+ evidence schema 29. Published v2 schemas 27 and 28 and exact v1 schema 26 remain
152
+ readable. Versions 27–29 exclude raw registration payloads, expanded
126
153
  contacts, credentials, complete query-bearing URLs and provider payloads;
127
- schema 28 can also retain the bounded, separately attributed registrar-standing
128
- projection shown by Lookup.
154
+ schemas 28 and 29 also retain the bounded registrar-standing projection.
155
+ Schema 29 identifies the hostname used for DNS, TLS and web observations,
156
+ separately from the registrable domain used by registration sources. Older
157
+ evidence retains its original collection scope.
129
158
 
130
159
  `verify-artifact` checks a recognised structure and its applicable integrity
131
160
  contract. `interchange-report` describes retained and omitted fields.
@@ -133,6 +162,45 @@ contract. `interchange-report` describes retained and omitted fields.
133
162
  validity and signer trust separate. None of these checks establishes that
134
163
  evidence is accurate, current, safe to share or attributable to a person.
135
164
 
165
+ ### Signer trust
166
+
167
+ Use `verify-signature package.json --trust-store-file trust.json --json` to
168
+ check an explicitly selected fingerprint policy offline. The result contains
169
+ the ordinary signature verification and a separate current trust decision.
170
+ Only a matching `trusted` entry succeeds; unknown, `retired`, `revoked` or
171
+ future-reviewed entries return exit code 4, including with `--quiet`.
172
+ Malformed files return 2. Without this option, the existing verification
173
+ output is unchanged. A supplied `--public-key-file` must also match.
174
+
175
+ The trust file contains no keys. For example:
176
+
177
+ ```json
178
+ {
179
+ "schema": "whoisleuth.evidence-signer-trust-store",
180
+ "version": 1,
181
+ "entries": [{
182
+ "keyIdSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
183
+ "label": "Evidence reviewer",
184
+ "status": "trusted",
185
+ "updatedAt": "2026-09-01T00:00:00.000Z",
186
+ "note": "Fingerprint confirmed through the established contact channel."
187
+ }]
188
+ }
189
+ ```
190
+
191
+ Replace the example fingerprint with the SHA-256 fingerprint of the signer's
192
+ SPKI DER public-key bytes, confirmed through an authenticated channel—not
193
+ merely copied from the package being checked. Review rotation and revocation
194
+ updates through that channel. On rotation, mark the old entry `retired` and
195
+ optionally record `successorKeyIdSha256`; independently confirm and add the
196
+ replacement entry. Use `revoked` for a withdrawn trust decision. Neither a
197
+ successor link nor a claimed signing date overrides current status.
198
+
199
+ Files support 1,024 distinct entries within 4 MiB. Labels and single-line notes
200
+ allow 160 and 2,048 characters respectively. Reports include only the matching
201
+ entry and the exact file digest. Keep the file and any saved reports under your
202
+ own retention policy. No automatic key discovery, key storage or trust refresh occurs.
203
+
136
204
  ## Command-family boundaries
137
205
 
138
206
  - Evidence collection commands retain separate source states. A failed or
@@ -144,17 +212,22 @@ evidence is accurate, current, safe to share or attributable to a person.
144
212
  - Bulk applies one declared collection contract per target. Fast accepts up to
145
213
  500 targets and Deep up to 50; each target remains a separate request.
146
214
  - Respond commands package browser-created Cases and prepare local packets,
147
- reports and sharing reviews. They do not create durable Cases, submit,
148
- publish, notify or grant recipient authorisation.
215
+ reports and sharing reviews. The offline [`case` workflow](cli.md#local-case-files)
216
+ also creates and updates ordinary local Case files through explicit, conflict-checked
217
+ output. Neither workflow submits, publishes, notifies or grants recipient authorisation.
149
218
  - Assurance, comparison and calibration commands describe supplied or retained
150
219
  evidence. They do not tune the running model, change infrastructure or turn an
151
220
  analyst label into observed truth.
152
221
  - `workflow-plan` lists fixed installed recipes without executing them.
222
+ `workflow-run --preview` validates a selected checkpoint and explains remaining
223
+ inputs and approvals offline, without running steps or rewriting the checkpoint.
153
224
  `workflow-run` executes only installed steps, requires approval for network
154
225
  work and pauses at unresolved analyst selections. Repeat
155
- `--select <step-id>=<path-or-value>` in placeholder order to resume a selected
156
- step; version-1 checkpoints remain readable and version 2 retains the exact
157
- selections in the local checkpoint.
226
+ `--select <step-id>=<path-or-value>` for remaining placeholders in order, or bind
227
+ a compatible earlier output with `--use-artifact <step-id>:<input-number>=<earlier-step-id>`.
228
+ Checkpoints retain exact selections and bindings and distinguish incomplete
229
+ collection from retryable failures; see [resuming a fixed workflow](cli.md#resuming-a-fixed-workflow)
230
+ for the supported versions and resume behaviour.
158
231
 
159
232
  Use the installed focused help for positional inputs, exact ceilings, options,
160
233
  network effects, outputs and command-specific exit behaviour.