@slicedearth/whoisleuth-cli 2.4.0 → 2.6.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 (340) hide show
  1. package/DISCLOSURE +1 -1
  2. package/NOTICE +2 -2
  3. package/cli/argument-values.mjs +55 -0
  4. package/cli/arguments.mjs +24 -470
  5. package/cli/artifact-validation/case-response.mjs +67 -9
  6. package/cli/artifact-validation/lookup-evidence.mjs +18 -4
  7. package/cli/artifact-validation/signed-review.mjs +61 -64
  8. package/cli/artifact-verify.mjs +11 -2
  9. package/cli/assurance-arguments.mjs +56 -0
  10. package/cli/assurance-command-definitions.mjs +179 -0
  11. package/cli/assurance-command-runner.mjs +1 -1
  12. package/cli/bounded-json.mjs +1 -1
  13. package/cli/bulk-checkpoint.mjs +1 -1
  14. package/cli/bulk-command-runner.mjs +6 -8
  15. package/cli/bulk.mjs +2 -3
  16. package/cli/case-command.mjs +99 -6
  17. package/cli/case-pack.mjs +19 -4
  18. package/cli/ci-report.mjs +6 -3
  19. package/cli/collection-arguments.mjs +123 -0
  20. package/cli/collection-command-definitions.mjs +330 -0
  21. package/cli/collection-preflight.mjs +8 -1
  22. package/cli/command-argument-grammar.mjs +8 -210
  23. package/cli/command-definition.mjs +330 -0
  24. package/cli/command-reference.mjs +55 -1388
  25. package/cli/command-seeds.mjs +18 -0
  26. package/cli/compare.mjs +1 -1
  27. package/cli/config-profile.mjs +1 -1
  28. package/cli/ct-event-intake.mjs +4 -4
  29. package/cli/discover.mjs +2 -2
  30. package/cli/discovery-observation-snapshot.mjs +2 -2
  31. package/cli/discovery-scan-command-runner.mjs +7 -9
  32. package/cli/discovery-scan.mjs +1 -1
  33. package/cli/discovery-snapshot.mjs +2 -2
  34. package/cli/discovery-workflow.mjs +4 -4
  35. package/cli/domain-control-monitor.mjs +6 -6
  36. package/cli/domain-control-observations.mjs +2 -1
  37. package/cli/domain-feed.mjs +61 -0
  38. package/cli/errors.mjs +5 -6
  39. package/cli/evidence-arguments.mjs +46 -0
  40. package/cli/evidence-command-definitions.mjs +69 -0
  41. package/cli/evidence-command-runner.mjs +2 -3
  42. package/cli/evidence-signing.mjs +3 -2
  43. package/cli/external-observation-mapping.mjs +2 -2
  44. package/cli/formatters/json.mjs +1 -13
  45. package/cli/formatters/terminal-command-formats.mjs +6 -0
  46. package/cli/formatters/terminal-lookup.mjs +6 -0
  47. package/cli/history-arguments.mjs +39 -0
  48. package/cli/history-command-definitions.mjs +88 -0
  49. package/cli/indicator-set-command.mjs +32 -0
  50. package/cli/inline-command-families.mjs +6 -47
  51. package/cli/inline-command-runner.mjs +4 -31
  52. package/cli/input.mjs +2 -2
  53. package/cli/intake-command.mjs +147 -0
  54. package/cli/interchange-report.mjs +4 -2
  55. package/cli/investigation-artifacts.mjs +3 -4
  56. package/cli/investigation-package-review.mjs +2 -0
  57. package/cli/investigation-plan.mjs +32 -154
  58. package/cli/investigation-recipes.mjs +177 -0
  59. package/cli/investigation-run.mjs +78 -12
  60. package/cli/local-mmdb-review.mjs +220 -17
  61. package/cli/lookalike-calibration.mjs +1 -1
  62. package/cli/lookup-brief.mjs +2 -2
  63. package/cli/lookup-command-runner.mjs +19 -35
  64. package/cli/lookup-diff.mjs +10 -9
  65. package/cli/lookup-plan.mjs +10 -14
  66. package/cli/lookup-reconcile.mjs +6 -5
  67. package/cli/lookup-timeline.mjs +7 -6
  68. package/cli/mail-header-review.mjs +24 -247
  69. package/cli/mail-review.mjs +9 -7
  70. package/cli/network-arguments.mjs +51 -0
  71. package/cli/network-command-definitions.mjs +130 -0
  72. package/cli/network-command-runner.mjs +43 -31
  73. package/cli/offline-evidence-review.mjs +85 -6
  74. package/cli/posture.mjs +1 -1
  75. package/cli/registry-fixture-scaffold.mjs +1 -1
  76. package/cli/retained-artifact-diff.mjs +8 -7
  77. package/cli/review-arguments.mjs +132 -0
  78. package/cli/review-command-definitions.mjs +279 -0
  79. package/cli/review-command-runner.mjs +72 -159
  80. package/cli/risk-calibration.mjs +14 -12
  81. package/cli/runner.mjs +20 -32
  82. package/cli/saved-lookup.mjs +2 -2
  83. package/cli/selected-input-worker.mjs +73 -0
  84. package/cli/sharing-review.mjs +5 -64
  85. package/cli/source-reliability.mjs +2 -2
  86. package/cli/support-arguments.mjs +49 -0
  87. package/cli/support-command-definitions.mjs +209 -0
  88. package/cli/support-command-runner.mjs +4 -4
  89. package/cli/watchlist-review.mjs +43 -0
  90. package/cli/workflow-arguments.mjs +100 -0
  91. package/cli/workflow-command-definitions.mjs +103 -0
  92. package/cli/workflow-command-runner.mjs +40 -1
  93. package/docs/cli-reference.md +27 -0
  94. package/docs/cli.md +322 -4
  95. package/docs/contextual-reviews.md +178 -0
  96. package/docs/infrastructure-observations.md +126 -0
  97. package/docs/offline-intake-context.md +213 -0
  98. package/lib/analyst-taxonomy.mjs +2 -40
  99. package/lib/application-version.mjs +1 -1
  100. package/lib/availability.mjs +13 -789
  101. package/lib/bounded-contract-normalizers.mjs +4 -0
  102. package/lib/bounded-json.mjs +2 -330
  103. package/lib/browser-library-profile.mjs +62 -84
  104. package/lib/candidate-provenance-bounds.mjs +2 -0
  105. package/lib/classify.mjs +1 -1
  106. package/lib/credential-form-attribution.mjs +136 -0
  107. package/lib/credential-surface-profile.mjs +6 -2
  108. package/lib/ct-query.mjs +2 -27
  109. package/lib/ct-response-bounds.mjs +2 -9
  110. package/lib/ct-search.mjs +83 -47
  111. package/lib/dmarc-discovery.mjs +62 -0
  112. package/lib/dns-convergence-review.mjs +21 -8
  113. package/lib/dns-delegation-health.mjs +35 -15
  114. package/lib/dns-inheritance-review.mjs +53 -63
  115. package/lib/dns-intelligence.mjs +27 -11
  116. package/lib/dns-query-coverage.mjs +40 -0
  117. package/lib/domain-assurance.mjs +1 -1
  118. package/lib/domain-change-packet.mjs +12 -13
  119. package/lib/domain-change-review.mjs +32 -14
  120. package/lib/domain-control-flight-recorder.mjs +103 -27
  121. package/lib/domain-control-manifest.mjs +25 -17
  122. package/lib/domain-posture-analysis.mjs +75 -7
  123. package/lib/domain-posture-parsers.mjs +9 -0
  124. package/lib/domain-posture.mjs +45 -25
  125. package/lib/domain-registration.mjs +392 -0
  126. package/lib/evidence-export-privacy.mjs +27 -17
  127. package/lib/evidence-export.mjs +3 -3
  128. package/lib/evidence-report.mjs +5 -1
  129. package/lib/external-intelligence-risk.mjs +2 -124
  130. package/lib/favicon.mjs +13 -4
  131. package/lib/generated/cisa-kev-catalog.mjs +41 -3
  132. package/lib/generated/registrar-standing-catalogue.mjs +18 -10
  133. package/lib/generated/retire-browser-catalog.mjs +332 -19
  134. package/lib/generated/{unicode-confusables-17.mjs → unicode-confusables.mjs} +33 -33
  135. package/lib/html-signals.mjs +13 -2
  136. package/lib/http-evidence-bounds.mjs +2 -8
  137. package/lib/http-intelligence.mjs +13 -1
  138. package/lib/idn-confusable-policy.mjs +6 -4
  139. package/lib/idn-confusables.mjs +1 -1
  140. package/lib/interchange-fidelity-registry.mjs +10 -0
  141. package/lib/lookup-child-profile-contract.mjs +28 -11
  142. package/lib/lookup-contract-primitives.mjs +1 -1
  143. package/lib/lookup-diagnostics.mjs +1 -23
  144. package/lib/lookup-network-evidence-bounds.mjs +1 -10
  145. package/lib/lookup-progress.mjs +50 -1
  146. package/lib/lookup-response-contract.mjs +70 -40
  147. package/lib/lookup-response.mjs +5 -15
  148. package/lib/lookup-source-progress.mjs +8 -22
  149. package/lib/lookup.mjs +1 -1
  150. package/lib/operation-budget.mjs +4 -0
  151. package/lib/opportunity-scoring.mjs +2 -107
  152. package/lib/outbound-identity.mjs +1 -1
  153. package/lib/page-fingerprints.mjs +18 -1
  154. package/lib/perceptual-hash-comparison.mjs +2 -34
  155. package/lib/perceptual-hash.mjs +36 -10
  156. package/lib/portable-generator.mjs +2 -29
  157. package/lib/project-metadata.mjs +2 -8
  158. package/lib/rdap-client.mjs +11 -7
  159. package/lib/registrable-domain.mjs +2 -56
  160. package/lib/registrar-standing-contract.mjs +1 -1
  161. package/lib/registrar-standing.mjs +9 -13
  162. package/lib/registry-capabilities.mjs +2 -2
  163. package/lib/registry-capability-catalogue.mjs +27 -19
  164. package/lib/risk-calibration-summary.mjs +2 -352
  165. package/lib/risk-scoring.mjs +2 -345
  166. package/lib/scoring-evidence-quality.mjs +2 -107
  167. package/lib/semantic-version.mjs +2 -54
  168. package/lib/service-binding-dns.mjs +46 -2
  169. package/lib/smtp-transport-review.mjs +48 -19
  170. package/lib/sslbl-certificates.generated.mjs +142 -139
  171. package/lib/static-html-analysis.mjs +32 -4
  172. package/lib/structured-data-identity.mjs +1 -1
  173. package/lib/technology-evidence-role.mjs +1 -51
  174. package/lib/threat-intelligence-manifests.mjs +1 -1
  175. package/lib/threat-intelligence-runtime.mjs +1 -1
  176. package/lib/threat-intelligence-targets.mjs +1 -1
  177. package/lib/threat-intelligence-types.mjs +2 -75
  178. package/lib/tls-intelligence.mjs +30 -5
  179. package/lib/typosquat-generator.mjs +11 -2
  180. package/lib/website-enrichment.mjs +404 -0
  181. package/lib/whois-authority.mjs +43 -5
  182. package/lib/whois-chain.mjs +12 -3
  183. package/lib/whois-common-formats.mjs +3 -1
  184. package/lib/whois-contacts.mjs +13 -2
  185. package/lib/whois-normalization.mjs +3 -1
  186. package/lib/whois-parser.mjs +5 -3
  187. package/package.json +15 -14
  188. package/packages/analysis/analyst-taxonomy.mjs +40 -0
  189. package/packages/analysis/bounded-json.mjs +330 -0
  190. package/packages/analysis/candidate-provenance-bounds.mjs +4 -0
  191. package/packages/analysis/cli-argument-grammar.mjs +216 -0
  192. package/packages/analysis/ct-query.mjs +27 -0
  193. package/packages/analysis/ct-response-bounds.mjs +9 -0
  194. package/packages/analysis/external-intelligence-risk.mjs +124 -0
  195. package/packages/analysis/http-evidence-bounds.mjs +8 -0
  196. package/packages/analysis/lookup-network-evidence-bounds.mjs +10 -0
  197. package/packages/analysis/opportunity-scoring.mjs +107 -0
  198. package/packages/analysis/perceptual-hash-comparison.mjs +34 -0
  199. package/packages/analysis/portable-generator.mjs +29 -0
  200. package/packages/analysis/project-metadata.mjs +8 -0
  201. package/packages/analysis/registrable-domain.mjs +56 -0
  202. package/packages/analysis/risk-calibration-summary.mjs +352 -0
  203. package/packages/analysis/risk-scoring.mjs +348 -0
  204. package/packages/analysis/scoring-evidence-quality.mjs +107 -0
  205. package/packages/analysis/semantic-version.mjs +54 -0
  206. package/packages/analysis/threat-intelligence-types.mjs +75 -0
  207. package/packages/cases/case-containment-handoff.mjs +195 -0
  208. package/packages/cases/case-evidence-links.mjs +151 -0
  209. package/packages/cases/case-evidence-model.mjs +89 -12
  210. package/packages/cases/case-evidence-quality.mjs +5 -0
  211. package/packages/cases/case-export-input.mjs +7 -5
  212. package/packages/cases/case-incident-context.mjs +52 -0
  213. package/packages/cases/case-markdown.mjs +11 -0
  214. package/packages/cases/case-migration-model.mjs +40 -24
  215. package/packages/cases/case-object-coverage.mjs +33 -0
  216. package/packages/cases/case-packet-correction.mjs +106 -0
  217. package/packages/cases/case-recheck-model.mjs +124 -36
  218. package/packages/cases/case-record-contracts.mjs +1 -1
  219. package/packages/cases/case-record-core.mjs +1 -1
  220. package/packages/cases/case-record-operations.mjs +111 -118
  221. package/packages/cases/case-record-projection.mjs +23 -4
  222. package/packages/cases/case-record-version-input.mjs +41 -0
  223. package/packages/cases/case-report.mjs +93 -27
  224. package/packages/cases/case-requested-evidence.mjs +146 -0
  225. package/packages/cases/case-response-actions.mjs +159 -1
  226. package/packages/cases/case-response-model.mjs +16 -1
  227. package/packages/cases/case-response-object.mjs +119 -0
  228. package/packages/cases/case-response-outcomes.mjs +108 -20
  229. package/packages/cases/case-response-packet-render.mjs +35 -12
  230. package/packages/cases/case-response-packet.mjs +55 -13
  231. package/packages/cases/case-response-records.mjs +0 -1
  232. package/packages/cases/case-response-review-inputs.mjs +60 -8
  233. package/packages/cases/case-storage-model.mjs +1 -1
  234. package/packages/cases/case-workflow-metadata.mjs +217 -0
  235. package/packages/cases/case-workflow-migration.mjs +43 -0
  236. package/packages/cases/http-summary.mjs +6 -1
  237. package/packages/comparison/favicon-similarity.mjs +1 -1
  238. package/packages/comparison/page-similarity.mjs +1 -1
  239. package/packages/comparison/relationship-evidence.mjs +21 -9
  240. package/packages/comparison/relationship-provenance.mjs +7 -1
  241. package/packages/contracts/analyst-interchange.mjs +35 -15
  242. package/packages/contracts/candidate-watch-review.mjs +54 -0
  243. package/packages/contracts/case-portability.mjs +360 -49
  244. package/packages/contracts/cli-command-semantics.mjs +5 -0
  245. package/packages/contracts/cli-grammar.mjs +6 -0
  246. package/packages/contracts/cli-lookup-brief.mjs +2 -0
  247. package/packages/contracts/context-review.mjs +25 -0
  248. package/packages/contracts/document-intake.mjs +11 -0
  249. package/packages/contracts/domain-control-flight-recorder.mjs +30 -14
  250. package/packages/contracts/domain-control-manifest.mjs +1 -1
  251. package/packages/contracts/domain-control-monitor.mjs +13 -2
  252. package/packages/contracts/domain-control-review.mjs +36 -15
  253. package/packages/contracts/external-observation-interchange.mjs +96 -28
  254. package/packages/contracts/har-review.mjs +2 -0
  255. package/packages/contracts/identity-events.mjs +4 -0
  256. package/packages/contracts/investigation-run.mjs +2 -0
  257. package/packages/contracts/ip-address.mjs +10 -0
  258. package/packages/contracts/lookup-evidence.mjs +3 -2
  259. package/packages/contracts/mail-authentication.mjs +5 -0
  260. package/packages/contracts/message-intake.mjs +37 -0
  261. package/packages/contracts/offline-comparison.mjs +4 -1
  262. package/packages/contracts/passive-mail.mjs +10 -0
  263. package/packages/contracts/risk-calibration.mjs +44 -29
  264. package/packages/contracts/schema-lifecycle.mjs +3 -1
  265. package/packages/contracts/web-capture.mjs +2 -2
  266. package/packages/contracts/workspace-portability.mjs +144 -28
  267. package/packages/evidence/collection-quality.mjs +67 -0
  268. package/packages/evidence/credential-form-attribution.mjs +60 -0
  269. package/packages/evidence/dns-query-outcome.mjs +72 -0
  270. package/packages/evidence/email-recipient.mjs +18 -0
  271. package/packages/evidence/image-regions.mjs +15 -0
  272. package/packages/evidence/lookup-target.mjs +5 -1
  273. package/packages/evidence/observation.mjs +2 -0
  274. package/packages/evidence/png-pixels.mjs +117 -0
  275. package/packages/evidence/public-address-policy.mjs +83 -0
  276. package/packages/evidence/record-identity.mjs +60 -16
  277. package/packages/evidence/technology-evidence-role.mjs +51 -0
  278. package/packages/interchange/defensive-indicator-export.mjs +264 -0
  279. package/packages/interchange/external-findings-import.mjs +36 -29
  280. package/packages/interchange/json-output.mjs +14 -0
  281. package/packages/interchange/managed-indicator-export.mjs +36 -0
  282. package/packages/interchange/managed-indicator-set.mjs +223 -0
  283. package/packages/interchange/misp-indicator-export.mjs +93 -0
  284. package/packages/interchange/sharing-policy.mjs +56 -0
  285. package/packages/interchange/stix-indicator-export.mjs +129 -0
  286. package/packages/interchange/web-capture-import.mjs +22 -15
  287. package/packages/investigation/acquisition-decision-packet.mjs +79 -1
  288. package/packages/investigation/bulk-mail-exposure.mjs +7 -13
  289. package/packages/investigation/capture-coverage.mjs +57 -0
  290. package/packages/investigation/connector-provenance-review.mjs +100 -0
  291. package/packages/investigation/context-review.mjs +35 -0
  292. package/packages/investigation/document-intake.mjs +87 -0
  293. package/packages/investigation/docx-intake.mjs +133 -0
  294. package/packages/investigation/domain-history-review.mjs +132 -0
  295. package/packages/investigation/domain-transition-review.mjs +49 -0
  296. package/packages/investigation/evidence-coverage-ledger.mjs +9 -1
  297. package/packages/investigation/har-intake.mjs +68 -0
  298. package/packages/investigation/identity-event-intake.mjs +131 -0
  299. package/packages/investigation/identity-incident-review.mjs +39 -0
  300. package/packages/investigation/incident-sequence-review.mjs +58 -0
  301. package/packages/investigation/infrastructure-observation.mjs +234 -0
  302. package/packages/investigation/intake-context.mjs +284 -0
  303. package/packages/investigation/intake-indicators.mjs +116 -0
  304. package/packages/investigation/intake-phones.mjs +155 -0
  305. package/packages/investigation/intake-report.mjs +20 -0
  306. package/packages/investigation/investigation-manifest.mjs +35 -9
  307. package/packages/investigation/link-intake.mjs +209 -0
  308. package/packages/investigation/lookup-asset-graph.mjs +1 -1
  309. package/packages/investigation/mail-authentication-review.mjs +222 -0
  310. package/packages/investigation/mail-header-identity.mjs +209 -0
  311. package/packages/investigation/message-intake.mjs +235 -0
  312. package/packages/investigation/page-behaviour.mjs +113 -0
  313. package/packages/investigation/pdf-intake.mjs +155 -0
  314. package/packages/investigation/platform-continuity-review.mjs +60 -0
  315. package/packages/investigation/qr-intake.mjs +56 -0
  316. package/packages/investigation/requested-action-hints.mjs +11 -0
  317. package/packages/investigation/selected-input-review.mjs +17 -0
  318. package/packages/investigation/storefront-review.mjs +70 -0
  319. package/packages/monitoring/domain-feed.mjs +321 -0
  320. package/packages/workspace/brand-candidate-workflow.mjs +351 -0
  321. package/packages/workspace/brand-keyword-campaign.mjs +231 -0
  322. package/packages/workspace/brand-profile-model.mjs +48 -4
  323. package/packages/workspace/bulk-review-model.mjs +28 -26
  324. package/packages/workspace/bulk-session-model.mjs +27 -13
  325. package/packages/workspace/campaign-model.mjs +1 -1
  326. package/packages/workspace/candidate-watch-handoff.mjs +195 -0
  327. package/packages/workspace/detection-rule-model.mjs +11 -3
  328. package/packages/workspace/hostile-input.mjs +1 -1
  329. package/packages/workspace/investigation-guide.mjs +2 -2
  330. package/packages/workspace/investigation-template-model.mjs +26 -2
  331. package/packages/workspace/page-baseline.mjs +2 -2
  332. package/packages/workspace/relationship-observation-model.mjs +17 -13
  333. package/packages/workspace/shortlist-model.mjs +24 -7
  334. package/packages/workspace/watchlist-history.mjs +59 -16
  335. package/packages/workspace/watchlist-store.mjs +152 -11
  336. package/packages/workspace/website-snapshot-model.mjs +28 -3
  337. package/packages/workspace/workspace-archive-crypto.mjs +1 -1
  338. package/packages/workspace/workspace-archive.mjs +5 -4
  339. package/third-party-notices.txt +549 -16
  340. package/lib/hostname.mjs +0 -2
@@ -6,11 +6,12 @@ export const REGISTRAR_STANDING_LOOKUP_EVIDENCE_SCHEMA_VERSION = 28;
6
6
  export const LATEST_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION = REGISTRAR_STANDING_LOOKUP_EVIDENCE_SCHEMA_VERSION;
7
7
  export const HOSTNAME_SCOPED_LOOKUP_EVIDENCE_SCHEMA_VERSION = 29;
8
8
  export const PRIVACY_MINIMIZED_LOOKUP_EVIDENCE_SCHEMA_VERSION = PUBLISHED_V2_LOOKUP_EVIDENCE_SCHEMA_VERSION;
9
- export const LOOKUP_EVIDENCE_SCHEMA_VERSION = HOSTNAME_SCOPED_LOOKUP_EVIDENCE_SCHEMA_VERSION;
9
+ export const LOOKUP_EVIDENCE_SCHEMA_VERSION = 30;
10
10
  export const SUPPORTED_LOOKUP_EVIDENCE_SCHEMA_VERSIONS = Object.freeze([
11
11
  V1_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION,
12
12
  PUBLISHED_V2_LOOKUP_EVIDENCE_SCHEMA_VERSION,
13
13
  LATEST_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION,
14
+ HOSTNAME_SCOPED_LOOKUP_EVIDENCE_SCHEMA_VERSION,
14
15
  LOOKUP_EVIDENCE_SCHEMA_VERSION,
15
16
  ]);
16
17
  export const LOOKUP_EVIDENCE_PORTABLE_MAX_BYTES = 5 * 1024 * 1024;
@@ -31,5 +32,5 @@ export const LOOKUP_EVIDENCE_COMPATIBILITY = defineSchemaCompatibility({
31
32
  writeSemantics: 'read_only',
32
33
  byteBudget: LOOKUP_EVIDENCE_PORTABLE_MAX_BYTES,
33
34
  owner: 'packages/contracts/lookup-evidence.mts',
34
- note: 'Exact published versions 26, 27 and 28 remain replayable with their original collection scope. Version 29 identifies the hostname used for supporting DNS, TLS and web observations; registration authority remains separate.',
35
+ note: 'Published versions 26–29 retain their original collection scope. Version 30 adds attributed password-form destinations; older page-wide flags are not form ownership evidence. Registration authority remains separate.',
35
36
  });
@@ -0,0 +1,5 @@
1
+ export const MAX_AUTHENTICATION_HEADERS = 512;
2
+ export const MAX_AUTHENTICATION_CLAUSES = 64;
3
+ export const MAX_AUTHENTICATION_VALUE_LENGTH = 16 * 1024;
4
+ export const MAIL_AUTHENTICATION_METHODS = Object.freeze(['spf', 'dkim', 'dmarc', 'arc']);
5
+ export const MAIL_AUTHENTICATION_PROPERTIES = ['smtp.mailfrom', 'smtp.helo', 'header.d', 'header.i', 'header.from'];
@@ -0,0 +1,37 @@
1
+ export const MESSAGE_INTAKE_SCHEMA = 'whoisleuth.message-intake';
2
+ export const MESSAGE_INTAKE_VERSION = 2;
3
+ export const MESSAGE_INTAKE_LEGACY_VERSION = 1;
4
+ export const MESSAGE_INTAKE_KINDS = ['text', 'email', 'calendar', 'qr', 'pdf', 'docx', 'har', 'identity'];
5
+ export const MESSAGE_INTAKE_INPUTS = {
6
+ text: { label: 'Pasted text or links', accept: '.txt,text/plain', binary: false },
7
+ email: { label: 'Email (.eml, including nested messages)', accept: '.eml,message/rfc822', binary: false },
8
+ calendar: { label: 'Calendar invitation (.ics)', accept: '.ics,text/calendar', binary: false },
9
+ qr: { label: 'QR image (still PNG)', accept: '.png,image/png', binary: true },
10
+ pdf: { label: 'PDF document', accept: '.pdf,application/pdf', binary: true },
11
+ docx: { label: 'Word document (.docx)', accept: '.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document', binary: true },
12
+ har: { label: 'HTTP archive (.har)', accept: '.har,application/json', binary: false },
13
+ identity: { label: 'Identity events (selected JSON)', accept: '.json,application/json', binary: false },
14
+ };
15
+ export const IDENTITY_ACTIONS = [
16
+ { id: 'opened_link', label: 'Opened the link' },
17
+ { id: 'entered_password', label: 'Entered a password' },
18
+ { id: 'approved_signin', label: 'Approved a sign-in or MFA request' },
19
+ { id: 'granted_consent', label: 'Granted application consent' },
20
+ { id: 'entered_device_code', label: 'Entered a device code' },
21
+ { id: 'executed_command', label: 'Ran a command or installed software' },
22
+ ];
23
+ // Byte admission, extraction work and decoded pixels are independent bounds.
24
+ export const MAX_MESSAGE_INTAKE_BYTES = 16 * 1024 * 1024;
25
+ export const MAX_MESSAGE_PARTS = 256;
26
+ export const MAX_MESSAGE_DEPTH = 12;
27
+ export const MAX_MESSAGE_HTML_NODES = 50_000;
28
+ export const MAX_INTAKE_LINKS = 512;
29
+ export const MAX_INTAKE_URL_LENGTH = 8_192;
30
+ export const MAX_EMBEDDED_LINK_DEPTH = 8;
31
+ export const MAX_AUTH_SCOPES = 64;
32
+ export const MAX_INTAKE_INDICATORS = 512;
33
+ export const MAX_INTAKE_INDICATOR_CANDIDATES = 4_096;
34
+ export const INTAKE_DISTRIBUTION_CHANNELS = ['email', 'sms', 'messaging', 'social', 'advertisement', 'website', 'document', 'other', 'unknown'];
35
+ export const INTAKE_TEXT_BASES = ['supplied_text', 'manual_transcription', 'ocr_text', 'unknown'];
36
+ export const INTAKE_PHONE_ROLES = ['advertised_support_contact', 'sender_or_caller_id_claim', 'unknown'];
37
+ export const MESSAGE_ACTION_HINTS = ['clipboard_instruction', 'shell_instruction', 'verification_prompt', 'device_code_instruction', 'consent_instruction'];
@@ -10,7 +10,10 @@ export const CLI_COMPARISON_LEDGER_SCHEMA = 'whoisleuth.cli.comparison-ledger';
10
10
  export const CLI_COMPARISON_LEDGER_VERSION = 1;
11
11
  export const MAX_RETAINED_ARTIFACT_DIFF_BYTES = 8 * 1024 * 1024;
12
12
  export const RELATIONSHIP_EVIDENCE_SCHEMA = 'whoisleuth.relationship-evidence';
13
- export const RELATIONSHIP_EVIDENCE_VERSION = 3;
13
+ export const RELATIONSHIP_EVIDENCE_VERSION = 4;
14
+ export const SUPPORTED_RELATIONSHIP_EVIDENCE_VERSIONS = Object.freeze([2, 3, RELATIONSHIP_EVIDENCE_VERSION]);
15
+ export const RELATIONSHIP_SOURCE_PROVENANCE_VERSION = 3;
16
+ export const RELATIONSHIP_PUBLIC_ADDRESS_VERSION = 4;
14
17
  export const TLS_RELATIONSHIP_PROFILE_VERSION = 2;
15
18
  export const SUPPORTED_TLS_RELATIONSHIP_PROFILE_VERSIONS = Object.freeze([TLS_RELATIONSHIP_PROFILE_VERSION]);
16
19
  export const OFFLINE_COMPARISON_COMPATIBILITY_FACADES = Object.freeze([
@@ -0,0 +1,10 @@
1
+ /** Stable interchange identities describe DNS publication, not message authentication. */
2
+ export const PASSIVE_MAIL_LABELS = Object.freeze({
3
+ authenticated_mail: 'MX, SPF and DMARC observed',
4
+ evidence_incomplete: 'Mail DNS evidence incomplete',
5
+ mail_auth_gap: 'MX observed; SPF or DMARC absent',
6
+ mail_auth_incomplete: 'MX observed; policy evidence incomplete',
7
+ no_explicit_mx: 'No explicit MX observed',
8
+ null_mx: 'Null MX observed',
9
+ });
10
+ export const PASSIVE_MAIL_INTERPRETATION = 'The retained authenticated_mail state means MX, SPF and DMARC publications were observed; it does not establish policy validity, alignment, message authentication or delivery.';
@@ -1,8 +1,8 @@
1
1
  import { defineSchemaCompatibility } from "./schema-compatibility.mjs";
2
2
  import { defineSchemaLifecycleFamily } from "./schema-lifecycle.mjs";
3
3
  export const RISK_CALIBRATION_DATASET_SCHEMA = 'whoisleuth.risk-calibration-dataset';
4
- export const RISK_CALIBRATION_DATASET_VERSION = 2;
5
- export const SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS = Object.freeze([RISK_CALIBRATION_DATASET_VERSION]);
4
+ export const RISK_CALIBRATION_DATASET_VERSION = 3;
5
+ export const SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS = Object.freeze([2, RISK_CALIBRATION_DATASET_VERSION]);
6
6
  export const RISK_CALIBRATION_REPORT_SCHEMA = 'whoisleuth.cli.risk-calibration';
7
7
  export const RISK_CALIBRATION_REPORT_VERSION = 3;
8
8
  export const SUPPORTED_RISK_CALIBRATION_REPORT_VERSIONS = Object.freeze([RISK_CALIBRATION_REPORT_VERSION]);
@@ -82,7 +82,7 @@ export const RISK_CALIBRATION_EVIDENCE_OPTIONAL_KEYS = Object.freeze([
82
82
  'activityStatus', 'mutationTypes', 'domainAgeDays', 'faviconMatch',
83
83
  'faviconNearMatch', 'reusesOfficialAssets', 'hasPasswordField', 'hasMx',
84
84
  'hasSpf', 'hasDmarc', 'privacyProtected', 'phishingLanguageMatch',
85
- 'hasExternalFormAction', 'idnReferenceMatch', 'pageBaselineMatch',
85
+ 'hasExternalFormAction', 'hasExternalPasswordForm', 'idnReferenceMatch', 'pageBaselineMatch',
86
86
  'hasActiveBrandProfile', 'scanDepth', 'observedAt', 'threatIntelligence',
87
87
  ]);
88
88
  export const RISK_CALIBRATION_THREAT_INTELLIGENCE_KEYS = Object.freeze([
@@ -179,7 +179,7 @@ export const RISK_CALIBRATION_DATASET_COMPATIBILITY = defineSchemaCompatibility(
179
179
  writeSemantics: 'read_only',
180
180
  byteBudget: MAX_RISK_CALIBRATION_INPUT_BYTES,
181
181
  owner: 'packages/contracts/risk-calibration.mts',
182
- note: 'Offline labelled fixture input; version 2 adds bounded review context without live collection.',
182
+ note: 'Offline labelled fixture input. Version 2 retains bounded review context; version 3 adds explicit form attribution. Historical records remain readable without manufacturing missing associations.',
183
183
  });
184
184
  export const RISK_CALIBRATION_REPORT_COMPATIBILITY = defineSchemaCompatibility({
185
185
  id: 'cli.risk-calibration-report',
@@ -292,22 +292,22 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
292
292
  RISK_CALIBRATION_REPORT_COMPATIBILITY,
293
293
  ],
294
294
  contracts: [
295
- {
295
+ ...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map((version) => ({
296
296
  compatibilityId: RISK_CALIBRATION_DATASET_COMPATIBILITY.id,
297
297
  schema: RISK_CALIBRATION_DATASET_SCHEMA,
298
- version: RISK_CALIBRATION_DATASET_VERSION,
298
+ version,
299
299
  role: 'document',
300
- lifecycle: 'current',
300
+ lifecycle: version === RISK_CALIBRATION_DATASET_VERSION ? 'current' : 'legacy',
301
301
  readable: true,
302
- emitted: true,
302
+ emitted: version === RISK_CALIBRATION_DATASET_VERSION,
303
303
  exactKeys: false,
304
304
  extensionPolicy: 'discard_bounded',
305
305
  futureVersionBehaviour: 'reject',
306
306
  migrationTarget: null,
307
307
  canonicalisation: null,
308
308
  byteBudget: MAX_RISK_CALIBRATION_INPUT_BYTES,
309
- fixtureIds: ['risk-calibration-dataset-v2'],
310
- },
309
+ fixtureIds: [`risk-calibration-dataset-v${version}`],
310
+ })),
311
311
  {
312
312
  compatibilityId: RISK_CALIBRATION_REPORT_COMPATIBILITY.id,
313
313
  schema: RISK_CALIBRATION_REPORT_SCHEMA,
@@ -329,6 +329,20 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
329
329
  },
330
330
  ],
331
331
  fixtures: [
332
+ {
333
+ id: 'risk-calibration-dataset-v3',
334
+ path: 'test/fixtures/risk-calibration-dataset-v3.json',
335
+ bytes: 1_096,
336
+ sha256: 'a8e41c1325094aec5ef4731fdf9f487a20999729f6cc704e400c3d83db2a0753',
337
+ contentDigestSha256: null,
338
+ schema: RISK_CALIBRATION_DATASET_SCHEMA,
339
+ version: 3,
340
+ role: 'current',
341
+ expectation: 'accepted_exact',
342
+ expectedOutputFixtureId: null,
343
+ scope: 'repository',
344
+ shapeId: 'risk-calibration.dataset.v3',
345
+ },
332
346
  {
333
347
  id: 'risk-calibration-dataset-v2',
334
348
  path: 'test/fixtures/risk-calibration-dataset-v2.json',
@@ -336,8 +350,8 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
336
350
  sha256: 'bd650fe84923c61658d451c25d928bd5ff8e54ff585f4f059e6798c681f9a401',
337
351
  contentDigestSha256: null,
338
352
  schema: RISK_CALIBRATION_DATASET_SCHEMA,
339
- version: RISK_CALIBRATION_DATASET_VERSION,
340
- role: 'current',
353
+ version: 2,
354
+ role: 'historical',
341
355
  expectation: 'accepted_exact',
342
356
  expectedOutputFixtureId: null,
343
357
  scope: 'repository',
@@ -375,11 +389,11 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
375
389
  metadata: {
376
390
  enforcement: 'declarative_only',
377
391
  shapes: [
378
- ...[RISK_CALIBRATION_DATASET_VERSION].map((version) => ({
392
+ ...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map((version) => ({
379
393
  id: `risk-calibration.dataset.v${version}`,
380
394
  schema: RISK_CALIBRATION_DATASET_SCHEMA,
381
395
  versions: [version],
382
- objects: DATASET_SHAPE_OBJECTS,
396
+ objects: version === 2 ? DATASET_SHAPE_OBJECTS.map(object => ({ ...object, optionalKeys: object.optionalKeys.filter(key => key !== 'hasExternalPasswordForm') })) : DATASET_SHAPE_OBJECTS,
383
397
  fixedArrays: [],
384
398
  normalisation: 'project_known_fields',
385
399
  target: null,
@@ -609,7 +623,7 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
609
623
  operation: 'build-dataset-download',
610
624
  acceptedContracts: [],
611
625
  emittedContract: { schema: RISK_CALIBRATION_DATASET_SCHEMA, version: RISK_CALIBRATION_DATASET_VERSION, discriminator: null },
612
- shapeIds: ['risk-calibration.dataset.v2'],
626
+ shapeIds: [`risk-calibration.dataset.v${RISK_CALIBRATION_DATASET_VERSION}`],
613
627
  boundProfileIds: ['risk-calibration.dataset-bounds.v2'],
614
628
  hookIds: ['risk-calibration.browser.build-dataset', 'risk-calibration.browser.serialise-dataset'],
615
629
  serialisationProfileId: 'risk-calibration.dataset-json.v2',
@@ -624,9 +638,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
624
638
  id: 'risk-calibration.cli-detailed-json-stdout',
625
639
  plane: 'cli',
626
640
  operation: 'build-detailed-json-stdout',
627
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
641
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
628
642
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'detailed' } },
629
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-detailed'],
643
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-detailed'],
630
644
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-detailed.v3', 'risk-calibration.report-detailed-json-output.v3'],
631
645
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.cli.serialise-report'],
632
646
  serialisationProfileId: 'risk-calibration.report-json.v3',
@@ -641,9 +655,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
641
655
  id: 'risk-calibration.cli-dataset-read',
642
656
  plane: 'cli',
643
657
  operation: 'read-dataset',
644
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
658
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
645
659
  emittedContract: null,
646
- shapeIds: ['risk-calibration.dataset.v2'],
660
+ shapeIds: SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`),
647
661
  boundProfileIds: ['risk-calibration.dataset-bounds.v2'],
648
662
  hookIds: ['risk-calibration.cli.parse-dataset'],
649
663
  serialisationProfileId: null,
@@ -658,9 +672,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
658
672
  id: 'risk-calibration.cli-detailed-terminal-stdout',
659
673
  plane: 'cli',
660
674
  operation: 'build-detailed-terminal-stdout',
661
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
675
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
662
676
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'detailed' } },
663
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-detailed'],
677
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-detailed'],
664
678
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-detailed.v3'],
665
679
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.cli.format-terminal'],
666
680
  serialisationProfileId: null,
@@ -675,9 +689,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
675
689
  id: 'risk-calibration.cli-summary-json-stdout',
676
690
  plane: 'cli',
677
691
  operation: 'build-summary-json-stdout',
678
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
692
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
679
693
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'summary' } },
680
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-summary'],
694
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-summary'],
681
695
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-summary-output.v3'],
682
696
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.shared.build-summary', 'risk-calibration.cli.serialise-report'],
683
697
  serialisationProfileId: 'risk-calibration.report-json.v3',
@@ -692,9 +706,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
692
706
  id: 'risk-calibration.cli-detailed-json-file',
693
707
  plane: 'cli',
694
708
  operation: 'build-detailed-json-file',
695
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
709
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
696
710
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'detailed' } },
697
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-detailed'],
711
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-detailed'],
698
712
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-detailed.v3', 'risk-calibration.report-detailed-json-output.v3', 'risk-calibration.cli-private-output.v1'],
699
713
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.cli.serialise-report', 'risk-calibration.cli.write-private-file'],
700
714
  serialisationProfileId: 'risk-calibration.report-json.v3',
@@ -709,9 +723,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
709
723
  id: 'risk-calibration.cli-detailed-terminal-file',
710
724
  plane: 'cli',
711
725
  operation: 'build-detailed-terminal-file',
712
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
726
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
713
727
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'detailed' } },
714
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-detailed'],
728
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-detailed'],
715
729
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-detailed.v3', 'risk-calibration.cli-private-output.v1'],
716
730
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.cli.format-terminal', 'risk-calibration.cli.write-private-file'],
717
731
  serialisationProfileId: null,
@@ -726,9 +740,9 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
726
740
  id: 'risk-calibration.cli-summary-json-file',
727
741
  plane: 'cli',
728
742
  operation: 'build-summary-json-file',
729
- acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [RISK_CALIBRATION_DATASET_VERSION], mode: 'direct', discriminator: null }],
743
+ acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
730
744
  emittedContract: { schema: RISK_CALIBRATION_REPORT_SCHEMA, version: RISK_CALIBRATION_REPORT_VERSION, discriminator: { path: '$.mode', value: 'summary' } },
731
- shapeIds: ['risk-calibration.dataset.v2', 'risk-calibration.report.v3-summary'],
745
+ shapeIds: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS.map(version => `risk-calibration.dataset.v${version}`), 'risk-calibration.report.v3-summary'],
732
746
  boundProfileIds: ['risk-calibration.dataset-bounds.v2', 'risk-calibration.report-summary-output.v3', 'risk-calibration.cli-private-output.v1'],
733
747
  hookIds: ['risk-calibration.cli.parse-dataset', 'risk-calibration.cli.build-detailed', 'risk-calibration.shared.build-summary', 'risk-calibration.cli.serialise-report', 'risk-calibration.cli.write-private-file'],
734
748
  serialisationProfileId: 'risk-calibration.report-json.v3',
@@ -1176,6 +1190,7 @@ const DATASET_EVIDENCE_SPEC = objectOf([
1176
1190
  { key: 'privacyProtected', value: BOOLEAN_SPEC, optional: true },
1177
1191
  { key: 'phishingLanguageMatch', value: boundedText(MAX_RISK_CALIBRATION_STRING_LENGTH), optional: true },
1178
1192
  { key: 'hasExternalFormAction', value: BOOLEAN_SPEC, optional: true },
1193
+ { key: 'hasExternalPasswordForm', value: BOOLEAN_SPEC, optional: true },
1179
1194
  { key: 'idnReferenceMatch', value: BOOLEAN_SPEC, optional: true },
1180
1195
  { key: 'pageBaselineMatch', value: BOOLEAN_SPEC, optional: true },
1181
1196
  { key: 'hasActiveBrandProfile', value: BOOLEAN_SPEC, optional: true },
@@ -640,11 +640,12 @@ function copyHook(value, index, budget) {
640
640
  }
641
641
  function copySerialisationProfile(value, index, budget) {
642
642
  const label = `Schema lifecycle serialisation profile ${index + 1}`;
643
- const source = ordinaryRecord(value, SERIALISATION_PROFILE_KEYS, label, budget);
643
+ const source = ordinaryRecord(value, SERIALISATION_PROFILE_KEYS, label, budget, ['compactFallback']);
644
644
  if (source.mediaType !== 'application/json'
645
645
  || source.encoding !== 'utf-8'
646
646
  || source.bom !== false
647
647
  || (source.indentSpaces !== 0 && source.indentSpaces !== 2)
648
+ || (source.compactFallback !== undefined && (source.compactFallback !== true || source.indentSpaces !== 2))
648
649
  || typeof source.terminalLf !== 'boolean'
649
650
  || (source.propertyOrder !== 'normalised_fixed' && source.propertyOrder !== 'source_insertion')
650
651
  || (source.integrity !== 'none'
@@ -664,6 +665,7 @@ function copySerialisationProfile(value, index, budget) {
664
665
  encoding: 'utf-8',
665
666
  bom: false,
666
667
  indentSpaces: source.indentSpaces,
668
+ ...(source.compactFallback === true ? { compactFallback: true } : {}),
667
669
  terminalLf: source.terminalLf,
668
670
  propertyOrder: source.propertyOrder,
669
671
  canonicalisation: source.canonicalisation === null
@@ -1,8 +1,8 @@
1
- export { MAX_WEB_CAPTURE_MANIFEST_BYTES, WEB_CAPTURE_MANIFEST_SCHEMA, WEB_CAPTURE_MANIFEST_VERSION, WEB_CAPTURE_SUMMARY_SCHEMA, WEB_CAPTURE_SUMMARY_VERSION, } from "./analyst-interchange.mjs";
1
+ export { MAX_WEB_CAPTURE_MANIFEST_BYTES, WEB_CAPTURE_MANIFEST_SCHEMA, WEB_CAPTURE_MANIFEST_VERSION, WEB_CAPTURE_MANIFEST_SUPPORTED_VERSIONS, WEB_CAPTURE_SUMMARY_SCHEMA, WEB_CAPTURE_SUMMARY_VERSION, } from "./analyst-interchange.mjs";
2
2
  export const WEB_CAPTURE_DOM_DIGEST_SCHEMA = 'whoisleuth.dom-digest';
3
3
  export const WEB_CAPTURE_DOM_DIGEST_VERSION = 1;
4
4
  export const WEB_CAPTURE_COMPARISON_SCHEMA = 'whoisleuth.web-capture-comparison';
5
- export const WEB_CAPTURE_COMPARISON_VERSION = 3;
5
+ export const WEB_CAPTURE_COMPARISON_VERSION = 5;
6
6
  export const MAX_WEB_CAPTURE_DOM_DIGEST_BYTES = 1024 * 1024;
7
7
  export const MAX_WEB_CAPTURE_SCREENSHOT_BYTES = 10 * 1024 * 1024;
8
8
  export const MAX_WEB_CAPTURE_DOM_ELEMENTS = 20_000;