@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
package/cli/arguments.mjs CHANGED
@@ -1,420 +1,36 @@
1
1
  import { parseCommandArguments } from "./command-argument-grammar.mjs";
2
2
  import { CliUsageError, hasUnsafeCliText } from "./errors.mjs";
3
- import { parseCliFailPolicies } from "./fail-policy.mjs";
4
3
  import { isDirectLookupTarget } from "../lib/classify.mjs";
5
- import { CLI_COMMANDS, cliMetaActionForInvocation, isCliCommand, } from "./command-reference.mjs";
6
- const MAX_CLI_ARGUMENTS = 32;
7
- const MAX_CLI_ARGUMENT_LENGTH = 1024;
4
+ import { MAX_CLI_ARGUMENTS, MAX_CLI_ARGUMENT_LENGTH } from "../packages/contracts/cli-grammar.mjs";
5
+ import { CLI_COMMANDS, cliMetaActionForInvocation, isCliCommand } from "./command-reference.mjs";
6
+ import { commandHasOwner } from "./command-reference.mjs";
7
+ import { SUPPORT_ARGUMENT_PARSERS } from "./support-arguments.mjs";
8
+ import { ASSURANCE_ARGUMENT_PARSERS } from "./assurance-arguments.mjs";
9
+ import { COLLECTION_ARGUMENT_PARSERS } from "./collection-arguments.mjs";
10
+ import { NETWORK_ARGUMENT_PARSERS } from "./network-arguments.mjs";
11
+ import { REVIEW_ARGUMENT_PARSERS } from "./review-arguments.mjs";
12
+ import { EVIDENCE_ARGUMENT_PARSERS } from "./evidence-arguments.mjs";
13
+ import { WORKFLOW_ARGUMENT_PARSERS } from "./workflow-arguments.mjs";
14
+ import { HISTORY_ARGUMENT_PARSERS } from "./history-arguments.mjs";
15
+ const CLI_PARSERS = Object.freeze({
16
+ ...SUPPORT_ARGUMENT_PARSERS,
17
+ ...ASSURANCE_ARGUMENT_PARSERS,
18
+ ...COLLECTION_ARGUMENT_PARSERS,
19
+ ...NETWORK_ARGUMENT_PARSERS,
20
+ ...REVIEW_ARGUMENT_PARSERS,
21
+ ...EVIDENCE_ARGUMENT_PARSERS,
22
+ ...WORKFLOW_ARGUMENT_PARSERS,
23
+ ...HISTORY_ARGUMENT_PARSERS,
24
+ });
25
+ export function isCliCommandForOwner(args, owner) {
26
+ return commandHasOwner(args.action, owner);
27
+ }
8
28
  function boundedArgument(value) {
9
29
  if (typeof value !== 'string' || value.length > MAX_CLI_ARGUMENT_LENGTH || hasUnsafeCliText(value)) {
10
30
  throw new CliUsageError('Arguments must be bounded text without control characters.');
11
31
  }
12
32
  return value;
13
33
  }
14
- function terminalOptions(parsed) {
15
- return { quiet: parsed.hasOption('--quiet'), color: !parsed.hasOption('--no-color') };
16
- }
17
- function parseInspectArchiveArguments(parsed) {
18
- const expectedContentDigest = parsed.optionValue('--expect-content-digest');
19
- if (expectedContentDigest !== null && !/^sha256:[a-f0-9]{64}$/u.test(expectedContentDigest)) {
20
- throw new CliUsageError('--expect-content-digest requires sha256 followed by 64 lowercase hexadecimal characters.');
21
- }
22
- return {
23
- action: 'inspect-archive',
24
- source: parsed.positionalValue('source'),
25
- passphraseSource: parsed.optionValue('--passphrase-file'),
26
- search: parsed.optionValue('--search'),
27
- reveal: parsed.hasOption('--reveal'),
28
- requireMatch: parsed.hasOption('--require-match'),
29
- expectedContentDigest,
30
- output: parsed.hasOption('--json') ? 'json' : 'terminal',
31
- ...terminalOptions(parsed),
32
- };
33
- }
34
- function parseSignArtifactArguments(parsed) {
35
- return {
36
- action: 'sign-artifact',
37
- source: parsed.positionalValue('source'),
38
- privateKeySource: parsed.optionValue('--private-key-file'),
39
- };
40
- }
41
- function parseVerifySignatureArguments(parsed) {
42
- return {
43
- action: 'verify-signature',
44
- source: parsed.positionalValue('source'),
45
- publicKeySource: parsed.optionValue('--public-key-file'),
46
- output: parsed.hasOption('--json') ? 'json' : 'terminal',
47
- ...terminalOptions(parsed),
48
- };
49
- }
50
- function jsonOutput(parsed) {
51
- return parsed.hasOption('--json') ? 'json' : 'terminal';
52
- }
53
- function normalizedLabel(parsed, option, maximum) {
54
- const value = parsed.optionValue(option);
55
- if (value === null)
56
- return null;
57
- const normalized = value.replace(/\s+/gu, ' ').trim();
58
- if (!normalized || normalized.length > maximum) {
59
- throw new CliUsageError(`${option} requires a label of at most ${maximum} characters.`);
60
- }
61
- return normalized;
62
- }
63
- function failPolicies(parsed, command) {
64
- const value = parsed.optionValue('--fail-on');
65
- return value === null ? null : parseCliFailPolicies(value, command);
66
- }
67
- function parseOutput(parsed, formats) {
68
- return formats.find(([option]) => parsed.hasOption(option))?.[1] ?? 'terminal';
69
- }
70
- function singleInputAction(action, parsed, positionalName = 'source') {
71
- return {
72
- action,
73
- [positionalName === 'source' ? 'source' : positionalName]: parsed.positionalValue(positionalName),
74
- output: jsonOutput(parsed),
75
- ...terminalOptions(parsed),
76
- };
77
- }
78
- function parseLookupArguments(parsed) {
79
- const output = parseOutput(parsed, [
80
- ['--json', 'json'], ['--junit', 'junit'], ['--markdown', 'markdown'], ['--html', 'html'],
81
- ]);
82
- const selectedFailPolicies = failPolicies(parsed, 'lookup');
83
- return {
84
- action: 'lookup',
85
- query: parsed.positionalValue('target'),
86
- output,
87
- deep: parsed.hasOption('--deep'),
88
- detail: parsed.hasOption('--summary') ? 'summary' : parsed.hasOption('--verbose') ? 'verbose' : 'standard',
89
- strictExit: parsed.hasOption('--strict-exit'),
90
- events: parsed.hasOption('--events'),
91
- plan: parsed.hasOption('--plan'),
92
- includeAttribution: !parsed.hasOption('--no-attribution'),
93
- observerLabel: normalizedLabel(parsed, '--observer', 80),
94
- vantageLabel: normalizedLabel(parsed, '--vantage', 80),
95
- ...terminalOptions(parsed),
96
- ...(parsed.hasOption('--browse') ? { browse: true } : {}),
97
- ...(parsed.optionValue('--save-lookup') ? { saveLookup: parsed.optionValue('--save-lookup') } : {}),
98
- ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
99
- };
100
- }
101
- function parseManifestArguments(parsed) {
102
- const sources = parsed.positionalValues('artefacts');
103
- if (sources.some((source) => !source))
104
- throw new CliUsageError('manifest requires from 1 to 16 JSON artefact files.');
105
- if (new Set(sources).size !== sources.length)
106
- throw new CliUsageError('manifest artefact files must be different.');
107
- const configurationDigestSha256 = parsed.optionValue('--configuration-digest');
108
- if (configurationDigestSha256 !== null && !/^sha256:[a-f0-9]{64}$/u.test(configurationDigestSha256)) {
109
- throw new CliUsageError('--configuration-digest requires a sha256: hexadecimal digest.');
110
- }
111
- return {
112
- action: 'manifest',
113
- sources,
114
- workflow: parsed.optionValue('--workflow'),
115
- configurationDigestSha256,
116
- output: jsonOutput(parsed),
117
- ...terminalOptions(parsed),
118
- };
119
- }
120
- function parseBulkArguments(parsed) {
121
- const deep = parsed.hasOption('--deep');
122
- const selectedFailPolicies = failPolicies(parsed, 'bulk');
123
- const output = parseOutput(parsed, [
124
- ['--json', 'json'], ['--jsonl', 'jsonl'], ['--csv', 'csv'], ['--domains', 'domains'],
125
- ['--queries', 'queries'], ['--junit', 'junit'],
126
- ]);
127
- const filter = parsed.hasOption('--registered-only') ? 'registered'
128
- : parsed.hasOption('--inconclusive-only') ? 'inconclusive'
129
- : parsed.hasOption('--errors-only') ? 'errors' : 'all';
130
- return {
131
- action: 'bulk',
132
- source: parsed.positionalValue('source'),
133
- output,
134
- deep,
135
- concurrency: parsed.integerOption('--concurrency') ?? (deep ? 2 : 4),
136
- checkpoint: parsed.optionValue('--checkpoint'),
137
- resume: parsed.hasOption('--resume'),
138
- events: parsed.hasOption('--events'),
139
- plan: parsed.hasOption('--plan'),
140
- filter,
141
- ...terminalOptions(parsed),
142
- ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
143
- };
144
- }
145
- function discoveryValues(parsed) {
146
- const familyText = parsed.optionValue('--families');
147
- return {
148
- preset: (familyText ? 'custom' : parsed.optionValue('--preset') ?? 'all'),
149
- keyboardLayout: (parsed.optionValue('--keyboard') ?? 'qwerty'),
150
- tldText: parsed.optionValue('--tlds'),
151
- dictionarySource: parsed.optionValue('--dictionary'),
152
- familyText,
153
- };
154
- }
155
- function parseDiscoverArguments(parsed) {
156
- return {
157
- action: 'discover',
158
- seed: parsed.positionalValue('subject'),
159
- output: parseOutput(parsed, [['--json', 'json'], ['--jsonl', 'jsonl'], ['--domains', 'domains']]),
160
- ...discoveryValues(parsed),
161
- snapshotSource: parsed.optionValue('--snapshot'),
162
- ...terminalOptions(parsed),
163
- };
164
- }
165
- function parseDiscoverScanArguments(parsed) {
166
- const deep = parsed.hasOption('--deep');
167
- const selectedFailPolicies = failPolicies(parsed, 'discover-scan');
168
- const filter = parsed.hasOption('--registered-only') ? 'registered'
169
- : parsed.hasOption('--inconclusive-only') ? 'inconclusive'
170
- : parsed.hasOption('--acquisition-only') ? 'acquisition'
171
- : parsed.hasOption('--suppressed-only') ? 'suppressed' : 'all';
172
- return {
173
- action: 'discover-scan',
174
- seed: parsed.positionalValue('subject'),
175
- output: parseOutput(parsed, [['--json', 'json'], ['--jsonl', 'jsonl'], ['--csv', 'csv'], ['--domains', 'domains']]),
176
- ...discoveryValues(parsed),
177
- deep,
178
- scanLimit: parsed.integerOption('--scan-limit') ?? Math.min(100, deep ? 50 : 500),
179
- chunkSize: parsed.integerOption('--chunk-size') ?? 25,
180
- concurrency: parsed.integerOption('--concurrency') ?? (deep ? 2 : 4),
181
- checkpoint: parsed.optionValue('--checkpoint'),
182
- resume: parsed.hasOption('--resume'),
183
- resolverText: parsed.optionValue('--resolver'),
184
- observationSnapshot: parsed.optionValue('--observation-snapshot'),
185
- allowlistSource: parsed.optionValue('--allowlist'),
186
- filter,
187
- events: parsed.hasOption('--events'),
188
- plan: parsed.hasOption('--plan'),
189
- ...terminalOptions(parsed),
190
- ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
191
- };
192
- }
193
- function parsePostureArguments(parsed) {
194
- const mailProfile = parsed.optionValue('--mail-profile') ?? 'standard';
195
- return {
196
- action: 'posture',
197
- domain: parsed.positionalValue('domain'),
198
- output: parseOutput(parsed, [['--json', 'json'], ['--sarif', 'sarif']]),
199
- selectorText: parsed.optionValue('--selectors'),
200
- retiredSelectorText: parsed.optionValue('--retired-selectors'),
201
- mailProfile: mailProfile === 'defensive-no-mail' ? 'defensive_no_mail' : mailProfile,
202
- ownedDomain: parsed.hasOption('--owned-domain'),
203
- ...terminalOptions(parsed),
204
- };
205
- }
206
- function parseDnssecValidateArguments(parsed) {
207
- return {
208
- action: 'dnssec-validate',
209
- target: parsed.positionalValue('domain'),
210
- resolver: parsed.optionValue('--resolver'),
211
- trustAnchorSource: parsed.optionValue('--trust-anchor'),
212
- ownedOrAuthorized: true,
213
- output: jsonOutput(parsed),
214
- ...terminalOptions(parsed),
215
- };
216
- }
217
- function parseMailTransportArguments(parsed) {
218
- return {
219
- action: 'mail-transport',
220
- source: parsed.positionalValue('source'),
221
- resolver: parsed.optionValue('--resolver'),
222
- trustAnchorSource: parsed.optionValue('--trust-anchor'),
223
- ownedOrAuthorized: true,
224
- activeProbeAcknowledged: true,
225
- output: jsonOutput(parsed),
226
- ...terminalOptions(parsed),
227
- };
228
- }
229
- function parseTwoFileComparisonArguments(parsed, command) {
230
- const sources = parsed.positionalValues('sources');
231
- if (sources[0] === sources[1])
232
- throw new CliUsageError(`${command} requires two different input files.`);
233
- return { leftSource: sources[0], rightSource: sources[1], output: jsonOutput(parsed), ...terminalOptions(parsed) };
234
- }
235
- function parseVerifyArtifactArguments(parsed) {
236
- return {
237
- action: 'verify-artifact',
238
- source: parsed.positionalValue('source'),
239
- passphraseSource: parsed.optionValue('--passphrase-file'),
240
- manifestSource: parsed.optionValue('--manifest'),
241
- manifestEntryId: parsed.optionValue('--manifest-entry'),
242
- output: jsonOutput(parsed),
243
- strictExit: parsed.hasOption('--strict-exit'),
244
- ...terminalOptions(parsed),
245
- };
246
- }
247
- function parseMonitorOnceArguments(parsed) {
248
- const selectedFailPolicies = failPolicies(parsed, 'monitor-once');
249
- return {
250
- action: 'monitor-once',
251
- source: parsed.positionalValue('source'),
252
- previousSource: parsed.optionValue('--previous'),
253
- output: parseOutput(parsed, [['--json', 'json'], ['--junit', 'junit']]),
254
- limit: parsed.integerOption('--limit') ?? 20,
255
- concurrency: parsed.integerOption('--concurrency') ?? 2,
256
- ...terminalOptions(parsed),
257
- ...(selectedFailPolicies ? { failOn: selectedFailPolicies } : {}),
258
- };
259
- }
260
- function parseSharingReviewArguments(parsed) {
261
- const purpose = parsed.optionValue('--purpose').replace(/\s+/gu, ' ').trim();
262
- if (!purpose || purpose.length > 200)
263
- throw new CliUsageError('--purpose is limited to 200 characters.');
264
- return {
265
- action: 'sharing-review',
266
- source: parsed.positionalValue('source'),
267
- output: jsonOutput(parsed),
268
- marking: parsed.optionValue('--marking'),
269
- recipientScope: parsed.optionValue('--recipient-scope'),
270
- purpose,
271
- humanReviewed: parsed.hasOption('--human-reviewed'),
272
- personalDataReviewed: parsed.hasOption('--personal-data-reviewed'),
273
- redactionsConfirmed: parsed.hasOption('--redactions-confirmed'),
274
- ...terminalOptions(parsed),
275
- };
276
- }
277
- function parseWorkflowPlanArguments(parsed) {
278
- const options = { output: jsonOutput(parsed), ...terminalOptions(parsed) };
279
- if (parsed.hasOption('--list')) {
280
- if (parsed.allPositionals.length > 0)
281
- throw new CliUsageError('workflow-plan discovery options do not accept a subject.');
282
- return { action: 'workflow-plan', discovery: 'list', ...options };
283
- }
284
- if (parsed.hasOption('--explain')) {
285
- if (parsed.allPositionals.length > 0)
286
- throw new CliUsageError('workflow-plan discovery options do not accept a subject.');
287
- return { action: 'workflow-plan', discovery: 'explain', recipe: parsed.optionValue('--explain'), ...options };
288
- }
289
- if (parsed.allPositionals.length !== 2) {
290
- throw new CliUsageError('workflow-plan requires one fixed recipe and one subject, --list, or --explain <recipe>.');
291
- }
292
- return {
293
- action: 'workflow-plan',
294
- recipe: parsed.positionalValue('recipe'),
295
- subject: parsed.positionalValue('subject'),
296
- ...options,
297
- };
298
- }
299
- function parseWorkflowRunArguments(parsed) {
300
- const selections = parsed.optionValues('--select').map((value) => {
301
- const separator = value.indexOf('=');
302
- const stepId = separator === -1 ? '' : value.slice(0, separator);
303
- const selection = separator === -1 ? '' : value.slice(separator + 1);
304
- if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(stepId) || !selection.trim()) {
305
- throw new CliUsageError('--select requires <step-id>=<path-or-value>.');
306
- }
307
- if (selection.startsWith('-')) {
308
- throw new CliUsageError('--select values cannot start with a hyphen; prefix a file path with ./ when needed.');
309
- }
310
- return Object.freeze({ stepId, value: selection });
311
- });
312
- return {
313
- action: 'workflow-run',
314
- recipe: parsed.positionalValue('recipe'),
315
- subject: parsed.positionalValue('subject'),
316
- resumeSource: parsed.optionValue('--resume'),
317
- selections: Object.freeze(selections),
318
- approveNetwork: parsed.hasOption('--approve-network'),
319
- output: jsonOutput(parsed),
320
- ...terminalOptions(parsed),
321
- };
322
- }
323
- function parseDiffArguments(parsed) {
324
- const compared = parseTwoFileComparisonArguments(parsed, 'diff');
325
- const leftSessionId = parsed.optionValue('--left-session');
326
- const rightSessionId = parsed.optionValue('--right-session');
327
- for (const [option, value] of [['--left-session', leftSessionId], ['--right-session', rightSessionId]]) {
328
- if (value !== null && !/^[A-Za-z0-9_-]{1,128}$/u.test(value)) {
329
- throw new CliUsageError(`${option} requires one bounded saved-session ID.`);
330
- }
331
- }
332
- return { action: 'diff', ...compared, leftSessionId, rightSessionId };
333
- }
334
- function uniqueSources(parsed, command) {
335
- const sources = parsed.positionalValues('sources');
336
- if (new Set(sources).size !== sources.length)
337
- throw new CliUsageError(`${command} input files must be different.`);
338
- return sources;
339
- }
340
- const CLI_PARSERS = Object.freeze({
341
- completion: (parsed) => ({ action: 'completion', shell: parsed.positionalValue('shell') }),
342
- doctor: (parsed) => ({ action: 'doctor', network: parsed.hasOption('--network'), output: jsonOutput(parsed), ...terminalOptions(parsed) }),
343
- commands: (parsed) => ({
344
- action: 'commands', output: jsonOutput(parsed), common: parsed.hasOption('--common'),
345
- group: parsed.optionValue('--group'),
346
- mode: parsed.optionValue('--mode'),
347
- ...terminalOptions(parsed),
348
- }),
349
- manual: () => ({ action: 'manual' }),
350
- manifest: parseManifestArguments,
351
- 'map-observations': (parsed) => singleInputAction('map-observations', parsed),
352
- 'oam-export': (parsed) => singleInputAction('oam-export', parsed),
353
- lookup: parseLookupArguments,
354
- bulk: parseBulkArguments,
355
- 'ct-search': (parsed) => singleInputAction('ct-search', parsed, 'keyword'),
356
- 'ct-intake': (parsed) => singleInputAction('ct-intake', parsed),
357
- discover: parseDiscoverArguments,
358
- 'discover-scan': parseDiscoverScanArguments,
359
- posture: parsePostureArguments,
360
- http: (parsed) => singleInputAction('http', parsed, 'domain'),
361
- tls: (parsed) => singleInputAction('tls', parsed, 'hostname'),
362
- 'dnssec-validate': parseDnssecValidateArguments,
363
- 'mail-transport': parseMailTransportArguments,
364
- 'registry-support': (parsed) => ({
365
- action: 'registry-support', target: parsed.positionalValue('domain-or-suffix'),
366
- output: jsonOutput(parsed), ...terminalOptions(parsed),
367
- }),
368
- 'registry-doctor': (parsed) => singleInputAction('registry-doctor', parsed),
369
- 'registry-cohort': (parsed) => singleInputAction('registry-cohort', parsed),
370
- 'registry-scaffold': (parsed) => ({
371
- action: 'registry-scaffold', profile: parsed.optionValue('--profile'), suffix: parsed.optionValue('--suffix'),
372
- scenario: parsed.optionValue('--scenario'),
373
- }),
374
- 'risk-calibrate': (parsed) => ({
375
- action: 'risk-calibrate', source: parsed.positionalValue('source'),
376
- output: parsed.hasOption('--json') ? 'json' : parsed.hasOption('--summary-json') ? 'summary_json' : 'terminal',
377
- ...terminalOptions(parsed),
378
- }),
379
- 'lookalike-calibrate': (parsed) => singleInputAction('lookalike-calibrate', parsed),
380
- 'verify-artifact': parseVerifyArtifactArguments,
381
- 'interchange-report': (parsed) => ({
382
- action: 'interchange-report', source: parsed.positionalValue('source'),
383
- passphraseSource: parsed.optionValue('--passphrase-file'), output: jsonOutput(parsed), ...terminalOptions(parsed),
384
- }),
385
- 'inspect-archive': parseInspectArchiveArguments,
386
- 'sign-artifact': parseSignArtifactArguments,
387
- 'verify-signature': parseVerifySignatureArguments,
388
- 'source-report': (parsed) => singleInputAction('source-report', parsed),
389
- compare: (parsed) => singleInputAction('compare', parsed),
390
- 'page-compare': (parsed) => ({ action: 'page-compare', ...parseTwoFileComparisonArguments(parsed, 'page-compare') }),
391
- 'mail-review': (parsed) => singleInputAction('mail-review', parsed),
392
- 'mail-headers': (parsed) => singleInputAction('mail-headers', parsed),
393
- 'review-evidence': (parsed) => ({
394
- action: 'review-evidence', source: parsed.positionalValue('source'), mmdbSource: parsed.optionValue('--mmdb'),
395
- output: jsonOutput(parsed), strictExit: parsed.hasOption('--strict-exit'), ...terminalOptions(parsed),
396
- }),
397
- brief: (parsed) => singleInputAction('brief', parsed),
398
- 'case-pack': (parsed) => ({
399
- action: 'case-pack', source: parsed.positionalValue('source'), output: jsonOutput(parsed),
400
- audience: parsed.optionValue('--audience'), reviewed: true, ...terminalOptions(parsed),
401
- }),
402
- 'domain-control': (parsed) => singleInputAction('domain-control', parsed),
403
- 'monitor-once': parseMonitorOnceArguments,
404
- assurance: (parsed) => singleInputAction('assurance', parsed),
405
- 'change-packet': (parsed) => singleInputAction('change-packet', parsed),
406
- 'sharing-review': parseSharingReviewArguments,
407
- 'workflow-plan': parseWorkflowPlanArguments,
408
- 'workflow-run': parseWorkflowRunArguments,
409
- diff: parseDiffArguments,
410
- reconcile: (parsed) => ({ action: 'reconcile', sources: uniqueSources(parsed, 'reconcile'), output: jsonOutput(parsed), ...terminalOptions(parsed) }),
411
- timeline: (parsed) => ({ action: 'timeline', sources: uniqueSources(parsed, 'timeline'), output: jsonOutput(parsed), ...terminalOptions(parsed) }),
412
- export: (parsed) => ({
413
- action: 'export', source: parsed.positionalValue('source'),
414
- format: parsed.hasOption('--markdown') ? 'markdown' : parsed.hasOption('--html') ? 'html' : 'json',
415
- compact: parsed.hasOption('--compact'), includeAttribution: !parsed.hasOption('--no-attribution'),
416
- }),
417
- });
418
34
  function parseCliArguments(rawArgv) {
419
35
  if (!Array.isArray(rawArgv) || rawArgv.length > MAX_CLI_ARGUMENTS) {
420
36
  throw new CliUsageError(`At most ${MAX_CLI_ARGUMENTS} command arguments are supported.`);