@slicedearth/whoisleuth-cli 2.0.1 → 2.1.0

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 (95) hide show
  1. package/cli/arguments.mjs +21 -5
  2. package/cli/artifact-validation/case-response.mjs +771 -0
  3. package/cli/artifact-validation/investigation-capsule.mjs +426 -0
  4. package/cli/artifact-validation/lookup-evidence.mjs +718 -0
  5. package/cli/artifact-validation/signed-review.mjs +598 -0
  6. package/cli/artifact-validation/structure-primitives.mjs +105 -0
  7. package/cli/artifact-verify.mjs +1 -1
  8. package/cli/assurance-command-runner.mjs +324 -0
  9. package/cli/command-reference.mjs +1175 -843
  10. package/cli/completion.mjs +56 -9
  11. package/cli/discriminated-command-handlers.mjs +11 -0
  12. package/cli/doctor.mjs +2 -2
  13. package/cli/evidence-command-runner.mjs +41 -31
  14. package/cli/export-evidence.mjs +1 -1
  15. package/cli/fail-policy.mjs +33 -8
  16. package/cli/formatters/terminal-command-formats.mjs +437 -0
  17. package/cli/formatters/terminal-lookup.mjs +758 -0
  18. package/cli/formatters/terminal-metadata.mjs +58 -0
  19. package/cli/formatters/terminal-shared.mjs +83 -0
  20. package/cli/formatters/terminal.mjs +5 -1232
  21. package/cli/history-command-runner.mjs +132 -0
  22. package/cli/inline-command-families.mjs +45 -0
  23. package/cli/inline-command-runner.mjs +55 -0
  24. package/cli/investigation-plan.mjs +9 -2
  25. package/cli/investigation-run.mjs +114 -9
  26. package/cli/lookup-brief.mjs +141 -23
  27. package/cli/lookup-browser-view.mjs +289 -0
  28. package/cli/lookup-browser.mjs +3 -288
  29. package/cli/mail-review.mjs +2 -6
  30. package/cli/offline-artifact-validation.mjs +19 -0
  31. package/cli/review-command-runner.mjs +269 -0
  32. package/cli/runner.mjs +15 -972
  33. package/cli/saved-lookup.mjs +19 -2
  34. package/cli/support-command-runner.mjs +229 -0
  35. package/cli/workflow-command-runner.mjs +129 -0
  36. package/docs/cli-reference.md +16 -9
  37. package/docs/cli.md +4 -2
  38. package/lib/availability.mjs +12 -9
  39. package/lib/bounded-contract-normalizers.mjs +2 -9
  40. package/lib/browser-library-profile.mjs +1 -2
  41. package/lib/client-behavior-profile.mjs +1 -2
  42. package/lib/credential-surface-profile.mjs +1 -1
  43. package/lib/domain-posture-analysis.mjs +10 -1
  44. package/lib/domain-posture.mjs +51 -23
  45. package/lib/evidence-export.mjs +46 -5
  46. package/lib/evidence-report-markdown.mjs +4 -0
  47. package/lib/evidence-report.mjs +50 -0
  48. package/lib/generated/cisa-kev-catalog.mjs +34 -4
  49. package/lib/generated/registrar-standing-catalogue.mjs +367 -0
  50. package/lib/json-record.mjs +12 -0
  51. package/lib/lookup-child-profile-contract.mjs +858 -0
  52. package/lib/lookup-contract-primitives.mjs +98 -0
  53. package/lib/lookup-diagnostics.mjs +96 -0
  54. package/lib/lookup-network-evidence-bounds.mjs +1 -0
  55. package/lib/lookup-response.mjs +367 -0
  56. package/lib/lookup.mjs +28 -443
  57. package/lib/page-role-profile.mjs +1 -3
  58. package/lib/registrar-standing-catalogue-contract.mjs +70 -0
  59. package/lib/registrar-standing-contract.mjs +300 -0
  60. package/lib/registrar-standing.mjs +269 -0
  61. package/lib/registry-insights.mjs +2 -8
  62. package/lib/risk-scoring.mjs +26 -10
  63. package/lib/sslbl-certificates.generated.mjs +138 -136
  64. package/lib/structured-data-identity.mjs +1 -3
  65. package/lib/technology-evidence-role.mjs +51 -0
  66. package/lib/threat-intelligence-runtime.mjs +3 -3
  67. package/lib/threat-intelligence-types.mjs +13 -0
  68. package/lib/threatfox-intelligence.mjs +1 -3
  69. package/lib/tls-intelligence.mjs +1 -2
  70. package/lib/urlhaus-intelligence.mjs +1 -3
  71. package/lib/urlscan-intelligence.mjs +1 -3
  72. package/lib/website-security-posture.mjs +1 -2
  73. package/lib/website-technology.mjs +72 -23
  74. package/lib/whois-common-formats.mjs +276 -0
  75. package/lib/whois-dialects.mjs +534 -0
  76. package/lib/whois-parser-support.mjs +305 -0
  77. package/lib/whois-parser.mjs +135 -0
  78. package/lib/whois.mjs +6 -1187
  79. package/package.json +2 -2
  80. package/packages/cases/case-evidence-model.mjs +9 -0
  81. package/packages/cases/case-migration-model.mjs +17 -11
  82. package/packages/cases/case-response-model.mjs +13 -9
  83. package/packages/cases/case-response-packet.mjs +297 -112
  84. package/packages/comparison/page-similarity.mjs +23 -0
  85. package/packages/contracts/case-portability.mjs +225 -61
  86. package/packages/contracts/cli-lookup.mjs +4 -3
  87. package/packages/contracts/domain-control-manifest.mjs +1 -1
  88. package/packages/contracts/investigation-portability.mjs +1 -1
  89. package/packages/contracts/risk-calibration.mjs +2 -2
  90. package/packages/contracts/workspace-portability.mjs +34 -6
  91. package/packages/investigation/evidence-coverage-ledger.mjs +21 -0
  92. package/packages/investigation/lookup-claim-readiness.mjs +2 -2
  93. package/packages/workspace/website-snapshot-model.mjs +79 -6
  94. package/third-party-notices.txt +1 -1
  95. package/cli/artifact-structure.mjs +0 -2507
@@ -6,11 +6,21 @@ const STATE_LABELS = Object.freeze({
6
6
  expiring: 'expiring/pending delete',
7
7
  registered: 'registered',
8
8
  });
9
- // Version 7 caps each independent evidence family, treats generic operational
10
- // properties as supporting context, and reports collection quality separately
11
- // from the heuristic score. Missing evidence never contributes points.
12
- export const RISK_MODEL_VERSION = 7;
9
+ // Version 8 keeps unreviewed whole-page similarity as visible review context
10
+ // without assigning it Risk points. Reviewed favicon and official-asset
11
+ // observations remain bounded within the brand-presentation family, generic
12
+ // operational properties remain supporting context, and missing evidence never
13
+ // contributes points.
14
+ export const RISK_MODEL_VERSION = 8;
13
15
  export const RISK_REVIEW_THRESHOLD = 70;
16
+ const CURRENT_RISK_MODEL = Object.freeze({
17
+ modelVersion: RISK_MODEL_VERSION,
18
+ includePageBaselineMatch: false,
19
+ });
20
+ const RISK_MODEL_V7 = Object.freeze({
21
+ modelVersion: 7,
22
+ includePageBaselineMatch: true,
23
+ });
14
24
  const RISK_STATE_BASE = Object.freeze({
15
25
  registered: 6,
16
26
  for_sale: 4,
@@ -114,7 +124,7 @@ function scoreQuality(input) {
114
124
  }
115
125
  // Risk prioritizes a registered lookalike/typosquat domain for analyst review.
116
126
  // It is a heuristic indicator, never a maliciousness or safety verdict.
117
- function explainRiskScoreInternal(input, excludedFamily) {
127
+ function explainRiskScoreInternal(input, excludedFamily, model) {
118
128
  const state = input.availability ?? input.state;
119
129
  if (typeof state !== 'string' || !RISK_STATES.has(state))
120
130
  return null;
@@ -143,8 +153,9 @@ function explainRiskScoreInternal(input, excludedFamily) {
143
153
  add('brand-presentation', 'Favicon resembles an official Brand Profile site', 14);
144
154
  if (input.reusesOfficialAssets === true)
145
155
  add('brand-presentation', 'Official asset-host relationship observed', 6);
146
- if (input.pageBaselineMatch === true)
156
+ if (model.includePageBaselineMatch && input.pageBaselineMatch === true) {
147
157
  add('brand-presentation', 'Multiple independently compared page-identity components match the official baseline', 14);
158
+ }
148
159
  if (typeof input.phishingLanguageMatch === 'string' && input.phishingLanguageMatch.trim()) {
149
160
  add('credential-lure', 'Suspicious urgency language observed', 8);
150
161
  }
@@ -193,7 +204,7 @@ function explainRiskScoreInternal(input, excludedFamily) {
193
204
  'external-intelligence', 'corroboration', 'operational-support',
194
205
  ];
195
206
  return {
196
- modelVersion: RISK_MODEL_VERSION,
207
+ modelVersion: model.modelVersion,
197
208
  score,
198
209
  rawScore,
199
210
  capped: score !== rawScore,
@@ -205,16 +216,16 @@ function explainRiskScoreInternal(input, excludedFamily) {
205
216
  };
206
217
  }
207
218
  export function explainRiskScore(input) {
208
- return explainRiskScoreInternal(input, null);
219
+ return explainRiskScoreInternal(input, null, CURRENT_RISK_MODEL);
209
220
  }
210
221
  export function buildRiskScoreSensitivity(input) {
211
- const baseline = explainRiskScoreInternal(input, null);
222
+ const baseline = explainRiskScoreInternal(input, null, CURRENT_RISK_MODEL);
212
223
  if (!baseline)
213
224
  return null;
214
225
  const removableFamilies = REMOVABLE_RISK_FAMILIES
215
226
  .filter((family) => baseline.families.some((item) => item.id === family && item.contribution > 0));
216
227
  const scenarios = removableFamilies.map((excludedFamily) => {
217
- const result = explainRiskScoreInternal(input, excludedFamily);
228
+ const result = explainRiskScoreInternal(input, excludedFamily, CURRENT_RISK_MODEL);
218
229
  const score = result?.score ?? baseline.score;
219
230
  return Object.freeze({ excludedFamily, score, difference: score - baseline.score });
220
231
  }).sort((left, right) => left.score - right.score || left.excludedFamily.localeCompare(right.excludedFamily));
@@ -240,6 +251,11 @@ export function computeRiskScore(input) {
240
251
  }
241
252
  // Retained only for deterministic offline comparison of reviewed calibration
242
253
  // datasets. Runtime lookups always use the current model above.
254
+ export function explainRiskScoreV7(input) {
255
+ return explainRiskScoreInternal(input, null, RISK_MODEL_V7);
256
+ }
257
+ // Retained only for deterministic offline comparison of reviewed calibration
258
+ // datasets. Runtime lookups always use the current model above.
243
259
  export function explainRiskScoreV6(input) {
244
260
  const state = input.availability ?? input.state;
245
261
  if (typeof state !== 'string' || !RISK_STATES.has(state))