@slicedearth/whoisleuth-cli 2.3.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/NOTICE +8 -2
  2. package/README.md +19 -15
  3. package/bin/whoisleuth.mjs +8 -1
  4. package/cli/archive-content-digest.mjs +14 -0
  5. package/cli/archive-inspect.mjs +20 -53
  6. package/cli/argument-values.mjs +55 -0
  7. package/cli/arguments.mjs +24 -408
  8. package/cli/artifact-validation/case-response.mjs +65 -44
  9. package/cli/artifact-validation/investigation-capsule.mjs +52 -31
  10. package/cli/artifact-validation/lookup-evidence.mjs +15 -9
  11. package/cli/artifact-validation/signed-review.mjs +136 -68
  12. package/cli/artifact-validation/structure-primitives.mjs +1 -105
  13. package/cli/artifact-verify.mjs +92 -24
  14. package/cli/assurance-arguments.mjs +56 -0
  15. package/cli/assurance-command-definitions.mjs +179 -0
  16. package/cli/assurance-command-runner.mjs +40 -5
  17. package/cli/bagit-folder.mjs +57 -0
  18. package/cli/bagit-review.mjs +23 -0
  19. package/cli/bounded-json.mjs +1 -1
  20. package/cli/bulk-checkpoint.mjs +1 -1
  21. package/cli/bulk-command-runner.mjs +4 -2
  22. package/cli/bulk-output.mjs +29 -3
  23. package/cli/bulk.mjs +2 -3
  24. package/cli/case-command.mjs +212 -0
  25. package/cli/case-pack.mjs +50 -32
  26. package/cli/ci-report.mjs +6 -3
  27. package/cli/collection-arguments.mjs +123 -0
  28. package/cli/collection-command-definitions.mjs +330 -0
  29. package/cli/collection-preflight.mjs +8 -1
  30. package/cli/command-argument-grammar.mjs +8 -206
  31. package/cli/command-definition.mjs +329 -0
  32. package/cli/command-reference.mjs +94 -1357
  33. package/cli/command-seeds.mjs +18 -0
  34. package/cli/compare.mjs +1 -1
  35. package/cli/completion.mjs +298 -79
  36. package/cli/config-profile.mjs +8 -6
  37. package/cli/ct-event-intake.mjs +16 -16
  38. package/cli/discover.mjs +5 -4
  39. package/cli/discovery-observation-snapshot.mjs +46 -18
  40. package/cli/discovery-scan-command-runner.mjs +5 -3
  41. package/cli/discovery-scan.mjs +7 -4
  42. package/cli/discovery-snapshot.mjs +2 -2
  43. package/cli/discovery-workflow.mjs +5 -5
  44. package/cli/domain-control-monitor.mjs +50 -20
  45. package/cli/domain-control-observations.mjs +151 -103
  46. package/cli/errors.mjs +37 -6
  47. package/cli/evidence-arguments.mjs +46 -0
  48. package/cli/evidence-command-definitions.mjs +69 -0
  49. package/cli/evidence-command-runner.mjs +18 -8
  50. package/cli/evidence-signing.mjs +5 -4
  51. package/cli/external-observation-mapping.mjs +9 -10
  52. package/cli/formatters/terminal-command-formats.mjs +6 -0
  53. package/cli/formatters/terminal-lookup.mjs +24 -46
  54. package/cli/formatters/terminal-shared.mjs +5 -3
  55. package/cli/formatters/terminal-technology.mjs +114 -0
  56. package/cli/history-arguments.mjs +39 -0
  57. package/cli/history-command-definitions.mjs +88 -0
  58. package/cli/indicator-set-command.mjs +33 -0
  59. package/cli/inline-command-families.mjs +6 -46
  60. package/cli/inline-command-runner.mjs +4 -31
  61. package/cli/input.mjs +2 -2
  62. package/cli/intake-command.mjs +107 -0
  63. package/cli/interactive-launcher.mjs +2 -160
  64. package/cli/interchange-report.mjs +8 -10
  65. package/cli/investigation-artifacts.mjs +176 -0
  66. package/cli/investigation-checkpoint.mjs +10 -0
  67. package/cli/investigation-folder.mjs +114 -0
  68. package/cli/investigation-manifest.mjs +1 -112
  69. package/cli/investigation-package-review.mjs +103 -0
  70. package/cli/investigation-plan.mjs +38 -147
  71. package/cli/investigation-recipes.mjs +177 -0
  72. package/cli/investigation-run.mjs +256 -35
  73. package/cli/local-document-checkpoint.mjs +170 -0
  74. package/cli/local-mmdb-review.mjs +197 -17
  75. package/cli/lookalike-calibration.mjs +1 -1
  76. package/cli/lookup-brief.mjs +2 -2
  77. package/cli/lookup-browser.mjs +5 -12
  78. package/cli/lookup-command-runner.mjs +33 -39
  79. package/cli/lookup-diff.mjs +47 -12
  80. package/cli/lookup-plan.mjs +16 -14
  81. package/cli/lookup-reconcile.mjs +15 -12
  82. package/cli/lookup-timeline.mjs +7 -6
  83. package/cli/mail-header-review.mjs +24 -247
  84. package/cli/mail-review.mjs +75 -21
  85. package/cli/manual.mjs +1 -0
  86. package/cli/network-arguments.mjs +51 -0
  87. package/cli/network-command-definitions.mjs +130 -0
  88. package/cli/network-command-runner.mjs +45 -31
  89. package/cli/offline-evidence-review.mjs +39 -6
  90. package/cli/output-file.mjs +31 -5
  91. package/cli/posture.mjs +1 -1
  92. package/cli/registry-doctor.mjs +3 -1
  93. package/cli/registry-fixture-scaffold.mjs +1 -1
  94. package/cli/registry-support.mjs +1 -1
  95. package/cli/retained-artifact-diff.mjs +10 -9
  96. package/cli/review-arguments.mjs +131 -0
  97. package/cli/review-command-definitions.mjs +273 -0
  98. package/cli/review-command-runner.mjs +104 -149
  99. package/cli/risk-calibration.mjs +8 -8
  100. package/cli/runner.mjs +74 -37
  101. package/cli/saved-lookup.mjs +2 -2
  102. package/cli/selected-input-worker.mjs +63 -0
  103. package/cli/sharing-review.mjs +8 -80
  104. package/cli/signer-trust.mjs +104 -0
  105. package/cli/source-reliability.mjs +75 -84
  106. package/cli/support-arguments.mjs +49 -0
  107. package/cli/support-command-definitions.mjs +209 -0
  108. package/cli/support-command-runner.mjs +2 -2
  109. package/cli/terminal-input.mjs +168 -0
  110. package/cli/workflow-arguments.mjs +86 -0
  111. package/cli/workflow-command-definitions.mjs +78 -0
  112. package/cli/workflow-command-runner.mjs +75 -13
  113. package/docs/cli-reference.md +103 -30
  114. package/docs/cli.md +510 -25
  115. package/docs/contextual-reviews.md +155 -0
  116. package/lib/abort.mjs +4 -1
  117. package/lib/analyst-taxonomy.mjs +2 -40
  118. package/lib/application-version.mjs +1 -1
  119. package/lib/availability.mjs +27 -754
  120. package/lib/bounded-contract-normalizers.mjs +4 -0
  121. package/lib/bounded-file.mjs +3 -1
  122. package/lib/bounded-html-document.mjs +125 -0
  123. package/lib/bounded-json.mjs +2 -290
  124. package/lib/browser-library-profile.mjs +99 -130
  125. package/lib/browser-library-worker.mjs +112 -0
  126. package/lib/candidate-provenance-bounds.mjs +2 -0
  127. package/lib/classify.mjs +1 -1
  128. package/lib/client-behavior-profile.mjs +3 -3
  129. package/lib/ct-query.mjs +2 -27
  130. package/lib/ct-response-bounds.mjs +2 -9
  131. package/lib/ct-search.mjs +89 -46
  132. package/lib/dmarc-discovery.mjs +62 -0
  133. package/lib/dns-convergence-review.mjs +21 -8
  134. package/lib/dns-delegation-health.mjs +36 -22
  135. package/lib/dns-inheritance-review.mjs +207 -0
  136. package/lib/dns-intelligence.mjs +44 -29
  137. package/lib/dns-mx.mjs +1 -1
  138. package/lib/dns-query-coverage.mjs +40 -0
  139. package/lib/dnssec-evidence-validation.mjs +11 -3
  140. package/lib/domain-assurance.mjs +1 -1
  141. package/lib/domain-change-packet.mjs +18 -14
  142. package/lib/domain-change-review.mjs +40 -16
  143. package/lib/domain-control-flight-recorder.mjs +301 -124
  144. package/lib/domain-control-manifest.mjs +126 -58
  145. package/lib/domain-posture-analysis.mjs +41 -11
  146. package/lib/domain-posture-parsers.mjs +88 -6
  147. package/lib/domain-posture.mjs +120 -32
  148. package/lib/domain-registration.mjs +392 -0
  149. package/lib/evidence-export-privacy.mjs +568 -0
  150. package/lib/evidence-export.mjs +12 -593
  151. package/lib/evidence-report.mjs +7 -2
  152. package/lib/external-intelligence-risk.mjs +2 -124
  153. package/lib/favicon.mjs +117 -41
  154. package/lib/generated/cisa-kev-catalog.mjs +50 -4
  155. package/lib/generated/registrar-standing-catalogue.mjs +18 -10
  156. package/lib/generated/retire-browser-catalog.mjs +2742 -1034
  157. package/lib/generated/{unicode-confusables-17.mjs → unicode-confusables.mjs} +33 -33
  158. package/lib/html-signals.mjs +87 -85
  159. package/lib/http-evidence-bounds.mjs +2 -7
  160. package/lib/http-intelligence.mjs +52 -27
  161. package/lib/idn-confusable-policy.mjs +6 -4
  162. package/lib/idn-confusables.mjs +1 -1
  163. package/lib/interchange-fidelity-registry.mjs +10 -0
  164. package/lib/lookup-cache.mjs +34 -11
  165. package/lib/lookup-child-profile-contract.mjs +24 -15
  166. package/lib/lookup-contract-primitives.mjs +1 -1
  167. package/lib/lookup-diagnostics.mjs +2 -1
  168. package/lib/lookup-network-evidence-bounds.mjs +1 -10
  169. package/lib/lookup-progress.mjs +79 -13
  170. package/lib/lookup-response-contract.mjs +1077 -0
  171. package/lib/lookup-response.mjs +11 -24
  172. package/lib/lookup-source-progress.mjs +24 -35
  173. package/lib/lookup.mjs +49 -28
  174. package/lib/observed-network-context.mjs +43 -27
  175. package/lib/opportunity-scoring.mjs +2 -107
  176. package/lib/outbound-identity.mjs +1 -1
  177. package/lib/outbound-request-bounds.mjs +4 -1
  178. package/lib/page-fingerprints.mjs +87 -134
  179. package/lib/page-role-profile.mjs +12 -8
  180. package/lib/perceptual-hash-comparison.mjs +2 -34
  181. package/lib/perceptual-hash.mjs +79 -24
  182. package/lib/portable-generator.mjs +2 -29
  183. package/lib/project-metadata.mjs +2 -8
  184. package/lib/rdap-bootstrap.mjs +72 -22
  185. package/lib/rdap-client.mjs +26 -14
  186. package/lib/rdap-normalization.mjs +33 -18
  187. package/lib/rdap-search-workbench.mjs +1 -1
  188. package/lib/rdap-transport.mjs +47 -20
  189. package/lib/rdap-types.mjs +2 -1
  190. package/lib/rdap.mjs +18 -3
  191. package/lib/registrable-domain.mjs +2 -36
  192. package/lib/registrar-standing-contract.mjs +2 -1
  193. package/lib/registrar-standing.mjs +9 -13
  194. package/lib/registry-capabilities.mjs +7 -3
  195. package/lib/registry-capability-catalogue.mjs +29 -20
  196. package/lib/registry-dates.mjs +2 -190
  197. package/lib/registry-insights.mjs +56 -18
  198. package/lib/response-policy.mjs +86 -48
  199. package/lib/risk-calibration-summary.mjs +2 -338
  200. package/lib/risk-scoring.mjs +2 -345
  201. package/lib/rpki-evidence.mjs +8 -5
  202. package/lib/safe-fetch.mjs +54 -47
  203. package/lib/scoring-evidence-quality.mjs +2 -107
  204. package/lib/security-txt.mjs +10 -7
  205. package/lib/semantic-version.mjs +2 -54
  206. package/lib/service-binding-dns.mjs +35 -0
  207. package/lib/smtp-transport-review.mjs +75 -34
  208. package/lib/sslbl-certificates.generated.mjs +141 -138
  209. package/lib/static-html-analysis.mjs +117 -146
  210. package/lib/structured-data-identity.mjs +2 -1
  211. package/lib/technology-markup.mjs +100 -0
  212. package/lib/threat-intelligence-manifests.mjs +11 -139
  213. package/lib/threat-intelligence-runtime.mjs +24 -52
  214. package/lib/threat-intelligence-targets.mjs +6 -34
  215. package/lib/threat-intelligence-types.mjs +2 -36
  216. package/lib/typosquat-generator.mjs +29 -16
  217. package/lib/urlhaus-intelligence.mjs +8 -3
  218. package/lib/urlscan-intelligence.mjs +1 -1
  219. package/lib/website-enrichment.mjs +388 -0
  220. package/lib/website-security-posture.mjs +30 -6
  221. package/lib/website-technology.mjs +111 -71
  222. package/lib/whois-authority.mjs +55 -5
  223. package/lib/whois-chain.mjs +9 -2
  224. package/lib/whois-common-formats.mjs +5 -5
  225. package/lib/whois-contracts.mjs +2 -1
  226. package/lib/whois-dialects.mjs +2 -2
  227. package/lib/whois-normalization.mjs +3 -1
  228. package/lib/whois-parser-support.mjs +8 -1
  229. package/lib/whois-parser.mjs +5 -3
  230. package/lib/whois-transport.mjs +23 -7
  231. package/package.json +14 -14
  232. package/packages/analysis/analyst-taxonomy.mjs +40 -0
  233. package/packages/analysis/bounded-json.mjs +330 -0
  234. package/packages/analysis/candidate-provenance-bounds.mjs +4 -0
  235. package/packages/analysis/cli-argument-grammar.mjs +216 -0
  236. package/packages/analysis/ct-query.mjs +27 -0
  237. package/packages/analysis/ct-response-bounds.mjs +9 -0
  238. package/packages/analysis/external-intelligence-risk.mjs +124 -0
  239. package/packages/analysis/http-evidence-bounds.mjs +8 -0
  240. package/packages/analysis/lookup-network-evidence-bounds.mjs +10 -0
  241. package/packages/analysis/opportunity-scoring.mjs +107 -0
  242. package/packages/analysis/perceptual-hash-comparison.mjs +34 -0
  243. package/packages/analysis/portable-generator.mjs +29 -0
  244. package/packages/analysis/project-metadata.mjs +8 -0
  245. package/packages/analysis/registrable-domain.mjs +56 -0
  246. package/packages/analysis/risk-calibration-summary.mjs +352 -0
  247. package/packages/analysis/risk-scoring.mjs +345 -0
  248. package/packages/analysis/scoring-evidence-quality.mjs +107 -0
  249. package/packages/analysis/semantic-version.mjs +54 -0
  250. package/packages/analysis/threat-intelligence-types.mjs +75 -0
  251. package/packages/cases/case-attachment-model.mjs +83 -0
  252. package/packages/cases/case-evidence-links.mjs +135 -0
  253. package/packages/cases/case-evidence-model.mjs +229 -69
  254. package/packages/cases/case-evidence-quality.mjs +5 -0
  255. package/packages/cases/case-export-input.mjs +55 -0
  256. package/packages/cases/case-incident-context.mjs +52 -0
  257. package/packages/cases/case-markdown.mjs +11 -0
  258. package/packages/cases/case-migration-model.mjs +98 -48
  259. package/packages/cases/case-model.mjs +1 -0
  260. package/packages/cases/case-recheck-model.mjs +149 -0
  261. package/packages/cases/case-record-contracts.mjs +1 -1
  262. package/packages/cases/case-record-core.mjs +4 -3
  263. package/packages/cases/case-record-operations.mjs +123 -133
  264. package/packages/cases/case-record-projection.mjs +30 -20
  265. package/packages/cases/case-record-version-input.mjs +19 -0
  266. package/packages/cases/case-report.mjs +114 -67
  267. package/packages/cases/case-requested-evidence.mjs +146 -0
  268. package/packages/cases/case-response-actions.mjs +756 -0
  269. package/packages/cases/case-response-model.mjs +49 -1129
  270. package/packages/cases/case-response-outcomes.mjs +338 -0
  271. package/packages/cases/case-response-packet-render.mjs +157 -0
  272. package/packages/cases/case-response-packet-types.mjs +1 -0
  273. package/packages/cases/case-response-packet-vocabulary.mjs +48 -0
  274. package/packages/cases/case-response-packet.mjs +58 -593
  275. package/packages/cases/case-response-records.mjs +93 -0
  276. package/packages/cases/case-response-review-inputs.mjs +382 -0
  277. package/packages/cases/case-response-values.mjs +85 -0
  278. package/packages/cases/case-review-package.mjs +45 -0
  279. package/packages/cases/case-selection.mjs +46 -0
  280. package/packages/cases/case-storage-model.mjs +26 -1
  281. package/packages/cases/case-workflow-metadata.mjs +225 -0
  282. package/packages/cases/case-workflow-migration.mjs +43 -0
  283. package/packages/cases/http-summary.mjs +6 -1
  284. package/packages/cases/response-route-freshness.mjs +16 -0
  285. package/packages/comparison/capture-context.mjs +61 -0
  286. package/packages/comparison/comparison-ledger-bulk.mjs +4 -1
  287. package/packages/comparison/favicon-similarity.mjs +1 -1
  288. package/packages/comparison/page-similarity.mjs +3 -2
  289. package/packages/comparison/relationship-evidence.mjs +103 -14
  290. package/packages/comparison/relationship-provenance.mjs +99 -0
  291. package/packages/contracts/analyst-interchange.mjs +234 -0
  292. package/packages/contracts/analyst-review-state-contract.mjs +11 -0
  293. package/packages/contracts/analyst-review-state.mjs +5 -4
  294. package/packages/contracts/case-portability.mjs +370 -114
  295. package/packages/contracts/case-views-contract.mjs +12 -0
  296. package/packages/contracts/case-views.mjs +26 -0
  297. package/packages/contracts/cli-command-semantics.mjs +3 -0
  298. package/packages/contracts/cli-grammar.mjs +6 -0
  299. package/packages/contracts/cli-lookup-brief.mjs +2 -0
  300. package/packages/contracts/cli-lookup.mjs +0 -1
  301. package/packages/contracts/context-review.mjs +24 -0
  302. package/packages/contracts/document-intake.mjs +11 -0
  303. package/packages/contracts/domain-control-flight-recorder.mjs +98 -44
  304. package/packages/contracts/domain-control-manifest.mjs +128 -74
  305. package/packages/contracts/domain-control-monitor.mjs +59 -45
  306. package/packages/contracts/domain-control-review.mjs +200 -121
  307. package/packages/contracts/domain-name.mjs +21 -0
  308. package/packages/contracts/external-observation-interchange.mjs +2 -1
  309. package/packages/contracts/extracted-domain-lifecycle.mjs +11 -32
  310. package/packages/contracts/har-review.mjs +2 -0
  311. package/packages/contracts/http-url.mjs +2 -0
  312. package/packages/contracts/identity-events.mjs +4 -0
  313. package/packages/contracts/investigation-package-limits.mjs +24 -0
  314. package/packages/contracts/investigation-portability.mjs +56 -27
  315. package/packages/contracts/investigation-run.mjs +18 -0
  316. package/packages/contracts/ip-address.mjs +44 -0
  317. package/packages/contracts/lookup-evidence.mjs +35 -0
  318. package/packages/contracts/mail-authentication.mjs +5 -0
  319. package/packages/contracts/message-intake.mjs +31 -0
  320. package/packages/contracts/offline-comparison.mjs +4 -2
  321. package/packages/contracts/page-fingerprints.mjs +15 -0
  322. package/packages/contracts/passive-mail.mjs +10 -0
  323. package/packages/contracts/risk-calibration.mjs +0 -1
  324. package/packages/contracts/schema-compatibility.mjs +1 -1
  325. package/packages/contracts/schema-lifecycle.mjs +83 -153
  326. package/packages/contracts/selected-file-limits.mjs +6 -0
  327. package/packages/contracts/vulnerability-identifiers.mjs +5 -0
  328. package/packages/contracts/web-capture.mjs +10 -0
  329. package/packages/contracts/workspace-portability.mjs +219 -238
  330. package/packages/evidence/artifact-integrity.mjs +8 -2
  331. package/packages/evidence/artifact-structure.mjs +105 -0
  332. package/packages/evidence/collection-quality.mjs +67 -0
  333. package/packages/evidence/decision-fact.mjs +4 -1
  334. package/packages/evidence/dns-query-outcome.mjs +72 -0
  335. package/packages/evidence/domain-control-runtime.mjs +155 -27
  336. package/packages/evidence/domain-posture-context.mjs +79 -0
  337. package/packages/evidence/email-recipient.mjs +18 -0
  338. package/packages/evidence/image-regions.mjs +56 -0
  339. package/packages/evidence/latest-observations.mjs +28 -0
  340. package/packages/evidence/lookup-target.mjs +108 -0
  341. package/packages/evidence/observation.mjs +18 -1
  342. package/packages/evidence/passphrase-encryption.mjs +44 -0
  343. package/packages/evidence/png-pixels.mjs +117 -0
  344. package/packages/evidence/public-address-policy.mjs +83 -0
  345. package/packages/evidence/record-identity.mjs +72 -0
  346. package/packages/evidence/registry-dates.mjs +190 -0
  347. package/packages/evidence/retained-file.mjs +69 -0
  348. package/packages/evidence/review-age.mjs +14 -0
  349. package/packages/interchange/bagit.mjs +342 -0
  350. package/packages/interchange/bounded-zip-extraction.mjs +278 -0
  351. package/packages/interchange/crc32.mjs +17 -0
  352. package/packages/interchange/defensive-indicator-export.mjs +264 -0
  353. package/packages/interchange/external-findings-import.mjs +93 -61
  354. package/packages/interchange/managed-indicator-export.mjs +35 -0
  355. package/packages/interchange/managed-indicator-set.mjs +210 -0
  356. package/packages/interchange/misp-indicator-export.mjs +93 -0
  357. package/packages/interchange/sharing-policy.mjs +56 -0
  358. package/packages/interchange/stix-indicator-export.mjs +129 -0
  359. package/packages/interchange/web-capture-import.mjs +389 -0
  360. package/packages/investigation/acquisition-decision-packet.mjs +1 -1
  361. package/packages/investigation/bulk-mail-exposure.mjs +9 -14
  362. package/packages/investigation/capture-coverage.mjs +57 -0
  363. package/packages/investigation/connector-provenance-review.mjs +100 -0
  364. package/packages/investigation/context-review.mjs +35 -0
  365. package/packages/investigation/document-intake.mjs +81 -0
  366. package/packages/investigation/docx-intake.mjs +133 -0
  367. package/packages/investigation/domain-history-review.mjs +100 -0
  368. package/packages/investigation/domain-transition-review.mjs +47 -0
  369. package/packages/investigation/evidence-coverage-ledger.mjs +9 -1
  370. package/packages/investigation/har-intake.mjs +68 -0
  371. package/packages/investigation/identity-event-intake.mjs +131 -0
  372. package/packages/investigation/identity-incident-review.mjs +39 -0
  373. package/packages/investigation/incident-sequence-review.mjs +58 -0
  374. package/packages/investigation/intake-report.mjs +19 -0
  375. package/packages/investigation/investigation-bagit.mjs +14 -0
  376. package/packages/investigation/investigation-capsule.mjs +33 -5
  377. package/packages/investigation/investigation-manifest.mjs +200 -0
  378. package/packages/investigation/investigation-package-crypto.mjs +98 -0
  379. package/packages/investigation/investigation-package.mjs +200 -0
  380. package/packages/investigation/link-intake.mjs +179 -0
  381. package/packages/investigation/lookup-asset-graph-inputs.mjs +38 -0
  382. package/packages/investigation/lookup-asset-graph.mjs +161 -141
  383. package/packages/investigation/lookup-claim-readiness.mjs +18 -0
  384. package/packages/investigation/lookup-investigation-brief.mjs +3 -3
  385. package/packages/investigation/lookup-task-guidance.mjs +58 -0
  386. package/packages/investigation/mail-authentication-review.mjs +222 -0
  387. package/packages/investigation/mail-header-identity.mjs +209 -0
  388. package/packages/investigation/message-intake.mjs +195 -0
  389. package/packages/investigation/page-behaviour.mjs +113 -0
  390. package/packages/investigation/pdf-intake.mjs +155 -0
  391. package/packages/investigation/platform-continuity-review.mjs +60 -0
  392. package/packages/investigation/qr-intake.mjs +56 -0
  393. package/packages/investigation/requested-action-hints.mjs +11 -0
  394. package/packages/investigation/selected-input-review.mjs +17 -0
  395. package/packages/investigation/storefront-review.mjs +70 -0
  396. package/packages/monitoring/analyst-review-state.mjs +38 -90
  397. package/packages/workspace/brand-profile-model.mjs +160 -22
  398. package/packages/workspace/bulk-columns.mjs +17 -0
  399. package/packages/workspace/bulk-review-model.mjs +39 -31
  400. package/packages/workspace/bulk-session-model.mjs +112 -27
  401. package/packages/workspace/bulk-sort.mjs +1 -0
  402. package/packages/workspace/campaign-model.mjs +1 -1
  403. package/packages/workspace/case-views.mjs +102 -0
  404. package/packages/workspace/detection-rule-model.mjs +1 -1
  405. package/packages/workspace/hostile-input.mjs +29 -8
  406. package/packages/workspace/investigation-guide.mjs +2 -2
  407. package/packages/workspace/investigation-template-model.mjs +45 -6
  408. package/packages/workspace/page-baseline.mjs +20 -17
  409. package/packages/workspace/relationship-observation-model.mjs +54 -35
  410. package/packages/workspace/shortlist-model.mjs +14 -5
  411. package/packages/workspace/watchlist-history.mjs +30 -14
  412. package/packages/workspace/watchlist-store.mjs +24 -6
  413. package/packages/workspace/website-snapshot-model.mjs +98 -33
  414. package/packages/workspace/workspace-archive-crypto.mjs +41 -61
  415. package/packages/workspace/workspace-archive.mjs +90 -25
  416. package/third-party-notices.txt +577 -17
  417. package/lib/hostname.mjs +0 -38
  418. package/packages/investigation/bulk-review-export.mjs +0 -63
@@ -0,0 +1,12 @@
1
+ export const CASE_VIEWS_SCHEMA = 'whoisleuth.case-views';
2
+ export const CASE_VIEWS_VERSION = 1;
3
+ export const MAX_CASE_VIEWS = 100;
4
+ export const MAX_CASE_VIEW_NAME_LENGTH = 80;
5
+ export const MAX_CASE_VIEW_SEARCH_LENGTH = 512;
6
+ // Accommodates 100 views with maximum-length Unicode names and search text.
7
+ export const MAX_CASE_VIEWS_BYTES = 512 * 1024;
8
+ export const CASE_VIEW_SORTS = Object.freeze([
9
+ { value: 'updated', label: 'Recently updated' },
10
+ { value: 'domain', label: 'Domain' },
11
+ { value: 'status', label: 'Status' },
12
+ ]);
@@ -0,0 +1,26 @@
1
+ import { defineSchemaCompatibility } from "./schema-compatibility.mjs";
2
+ import { buildExtractedLifecycleFamily } from "./extracted-domain-lifecycle.mjs";
3
+ import { defineSchemaLifecycleFamily } from "./schema-lifecycle.mjs";
4
+ import { CASE_VIEWS_SCHEMA, CASE_VIEWS_VERSION, MAX_CASE_VIEWS_BYTES } from "./case-views-contract.mjs";
5
+ export const CASE_VIEWS_COMPATIBILITY = defineSchemaCompatibility({
6
+ id: 'browser.case-views', kind: 'browser_store', schema: CASE_VIEWS_SCHEMA,
7
+ currentVersion: CASE_VIEWS_VERSION, supportedVersions: [CASE_VIEWS_VERSION],
8
+ acceptsUnversionedLegacy: false, futureVersionBehavior: 'preserve_without_write',
9
+ migration: 'exact_current_only', writeSemantics: 'optimistic_replace',
10
+ byteBudget: MAX_CASE_VIEWS_BYTES, owner: 'packages/contracts/case-views.mts',
11
+ note: 'Workspace-local named Case filters. Saved views retain no result set and grant no collection authority; workspace exports include their names and search text.',
12
+ });
13
+ export const CASE_VIEWS_LIFECYCLE_FAMILY = /* @__PURE__ */ defineSchemaLifecycleFamily(/* @__PURE__ */ buildExtractedLifecycleFamily({
14
+ id: 'case-views', owner: 'packages/contracts/case-views.mts',
15
+ serializerModule: 'packages/workspace/case-views.mts', serializerExportName: 'serialiseCaseViewsJson',
16
+ plane: 'browser', projection: 'browser_import', retention: 'browser_indexeddb', notePolicy: 'allowed_bounded',
17
+ includedCategories: ['saved-filter-name', 'case-status-and-disposition', 'search-text', 'sort-order', 'authored-times'],
18
+ excludedCategories: ['matching-case-records', 'source-evidence', 'collection-authorisation', 'public-response-packets'],
19
+ formats: [{
20
+ descriptor: CASE_VIEWS_COMPATIBILITY, lifecycleSchema: CASE_VIEWS_SCHEMA,
21
+ requiredKeys: ['schema', 'version', 'views'], optionalKeys: [],
22
+ hook: { module: 'packages/workspace/case-views.mts', exportName: 'normalizeCaseViewsStore', role: 'normaliser', runtime: 'shared' },
23
+ fixtures: [{ id: 'case-views-v1', path: 'test/fixtures/extracted-domain-lifecycle/case-views-v1.json', version: 1,
24
+ bytes: 408, sha256: '015592dd0d6f4536b5960be9325b8d3b8c136eaab195d82383ab9a320a03f855' }],
25
+ }],
26
+ }));
@@ -76,8 +76,11 @@ export const CLI_COMMAND_SEMANTICS = Object.freeze({
76
76
  'page-compare': semantic('investigate', CAPABILITY_IDS.OFFLINE_REVIEW),
77
77
  'mail-review': semantic('investigate', CAPABILITY_IDS.OFFLINE_REVIEW),
78
78
  'mail-headers': semantic('investigate', CAPABILITY_IDS.OFFLINE_REVIEW),
79
+ intake: semantic('investigate', CAPABILITY_IDS.OFFLINE_REVIEW),
79
80
  'review-evidence': semantic('investigate', CAPABILITY_IDS.PORTABLE_EVIDENCE),
80
81
  brief: semantic('investigate', CAPABILITY_IDS.OFFLINE_REVIEW),
82
+ case: semantic('respond', CAPABILITY_IDS.ANALYST_CASES),
83
+ 'indicator-set': semantic('respond', CAPABILITY_IDS.PORTABLE_EVIDENCE),
81
84
  'case-pack': semantic('respond', CAPABILITY_IDS.PORTABLE_EVIDENCE),
82
85
  'domain-control': semantic('assure', CAPABILITY_IDS.PORTABLE_EVIDENCE),
83
86
  'monitor-once': semantic('assure', CAPABILITY_IDS.LOOKUP),
@@ -0,0 +1,6 @@
1
+ import { MAX_INVESTIGATION_MANIFEST_ARTIFACTS } from "./investigation-package-limits.mjs";
2
+ export const MAX_CLI_ARGUMENTS = MAX_INVESTIGATION_MANIFEST_ARTIFACTS + 32;
3
+ export const MAX_CLI_ARGUMENT_LENGTH = 1024;
4
+ export function hasUnsafeCliText(value) {
5
+ return /[\x00-\x1f\x7f-\x9f]|\p{Default_Ignorable_Code_Point}/u.test(value);
6
+ }
@@ -0,0 +1,2 @@
1
+ export const CLI_LOOKUP_BRIEF_SCHEMA = 'whoisleuth.cli.lookup-brief';
2
+ export const CLI_LOOKUP_BRIEF_VERSION = 3;
@@ -156,7 +156,6 @@ export const CLI_LOOKUP_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
156
156
  },
157
157
  ],
158
158
  metadata: {
159
- metadataVersion: 3,
160
159
  enforcement: 'declarative_only',
161
160
  shapes: [
162
161
  {
@@ -0,0 +1,24 @@
1
+ /** Common presentation of bounded, analyst-selected contextual evidence. */
2
+ export const CONTEXT_REVIEW_SCHEMA = 'whoisleuth.context-review';
3
+ export const CONTEXT_REVIEW_VERSION = 1;
4
+ export const DOMAIN_HISTORY_INPUT_SCHEMA = 'whoisleuth.domain-history.input';
5
+ export const DOMAIN_HISTORY_INPUT_VERSION = 1;
6
+ export const PLATFORM_CONTINUITY_INPUT_SCHEMA = 'whoisleuth.platform-continuity.input';
7
+ export const PLATFORM_CONTINUITY_INPUT_VERSION = 1;
8
+ export const STOREFRONT_INPUT_SCHEMA = 'whoisleuth.storefront-review.input';
9
+ export const STOREFRONT_INPUT_VERSION = 1;
10
+ export const CONNECTOR_INPUT_SCHEMA = 'whoisleuth.connector-review.input';
11
+ export const CONNECTOR_INPUT_VERSION = 1;
12
+ export const INCIDENT_SEQUENCE_INPUT_SCHEMA = 'whoisleuth.incident-sequence.input';
13
+ export const INCIDENT_SEQUENCE_INPUT_VERSION = 1;
14
+ export const CONTEXT_INPUT_CONTRACTS = [
15
+ { schema: DOMAIN_HISTORY_INPUT_SCHEMA, version: DOMAIN_HISTORY_INPUT_VERSION },
16
+ { schema: PLATFORM_CONTINUITY_INPUT_SCHEMA, version: PLATFORM_CONTINUITY_INPUT_VERSION },
17
+ { schema: STOREFRONT_INPUT_SCHEMA, version: STOREFRONT_INPUT_VERSION },
18
+ { schema: CONNECTOR_INPUT_SCHEMA, version: CONNECTOR_INPUT_VERSION },
19
+ { schema: INCIDENT_SEQUENCE_INPUT_SCHEMA, version: INCIDENT_SEQUENCE_INPUT_VERSION },
20
+ ];
21
+ export const CONTEXT_INPUT_SCHEMAS = CONTEXT_INPUT_CONTRACTS.map(input => input.schema);
22
+ export const MAX_CONTEXT_INPUT_BYTES = 16 * 1024 * 1024;
23
+ export const MAX_CONTEXT_RECORDS = 200;
24
+ export const CONTEXT_REVIEW_KINDS = ['domain_history', 'platform_continuity', 'storefront', 'connector', 'incident_sequence'];
@@ -0,0 +1,11 @@
1
+ /** Input admission, decoded XML, page work and pixels are independently bounded. */
2
+ export const MAX_DOCUMENT_PARTS = 512;
3
+ export const MAX_DOCUMENT_PAGES = 256;
4
+ export const MAX_DOCUMENT_DECODED_BYTES = 32 * 1024 * 1024;
5
+ export const MAX_DOCUMENT_TEXT_BYTES = 8 * 1024 * 1024;
6
+ export const MAX_DOCUMENT_XML_NODES = 200_000;
7
+ export const MAX_DOCUMENT_PAGE_OPERATIONS = 200_000;
8
+ export const MAX_DOCUMENT_XML_DEPTH = 64;
9
+ export const MAX_DOCUMENT_IMAGE_PIXELS = 16 * 1024 * 1024;
10
+ export const MAX_DOCUMENT_TOTAL_IMAGE_PIXELS = 64 * 1024 * 1024;
11
+ export const DOCUMENT_REVIEW_DEADLINE_MS = 60_000;
@@ -1,20 +1,25 @@
1
1
  import { defineSchemaCompatibility } from "./schema-compatibility.mjs";
2
2
  import { defineSchemaLifecycleFamily } from "./schema-lifecycle.mjs";
3
- import { MAX_DOMAIN_CONTROL_MANIFEST_BYTES, } from "./domain-control-manifest.mjs";
3
+ import { MAX_DOMAIN_CONTROL_MANIFEST_BYTES, MAX_CURRENT_DOMAIN_CONTROL_RECORDS, MAX_DOMAIN_CONTROL_DS_PRESENTATION_LENGTH, } from "./domain-control-manifest.mjs";
4
4
  import { MAX_DOMAIN_CONTROL_MONITOR_CONCURRENCY, MAX_DOMAIN_CONTROL_MONITOR_DOMAINS, MIN_DOMAIN_CONTROL_MONITOR_CONCURRENCY, MIN_DOMAIN_CONTROL_MONITOR_DOMAINS, } from "./domain-control-monitor.mjs";
5
5
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA = 'whoisleuth.domain-control-flight-recorder.input';
6
6
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA = 'whoisleuth.domain-control-flight-recorder';
7
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION = 1;
7
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION = 1;
8
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION = 3;
9
+ export const SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS = [PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION, 2, DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION];
8
10
  export const MIN_FLIGHT_RECORDER_OBSERVATIONS = 1;
9
11
  export const MAX_FLIGHT_RECORDER_OBSERVATIONS = 200;
10
12
  export const MAX_FLIGHT_RECORDER_WINDOWS = 40;
11
13
  export const MAX_FLIGHT_RECORDER_FIELDS = 24;
12
- export const MAX_FLIGHT_RECORDER_VALUES = 32;
14
+ export const PUBLIC_MAX_FLIGHT_RECORDER_VALUES = 32;
15
+ export const MAX_FLIGHT_RECORDER_VALUES = MAX_CURRENT_DOMAIN_CONTROL_RECORDS;
13
16
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_VALUE_INPUT_FACTOR = 2;
14
17
  export const MAX_FLIGHT_RECORDER_INPUT_VALUES = MAX_FLIGHT_RECORDER_VALUES
15
18
  * DOMAIN_CONTROL_FLIGHT_RECORDER_VALUE_INPUT_FACTOR;
19
+ export const PUBLIC_MAX_FLIGHT_RECORDER_INPUT_VALUES = PUBLIC_MAX_FLIGHT_RECORDER_VALUES * DOMAIN_CONTROL_FLIGHT_RECORDER_VALUE_INPUT_FACTOR;
16
20
  export const MAX_FLIGHT_RECORDER_SOURCE_LENGTH = 120;
17
- export const MAX_FLIGHT_RECORDER_VALUE_LENGTH = 500;
21
+ export const PUBLIC_MAX_FLIGHT_RECORDER_VALUE_LENGTH = 500;
22
+ export const MAX_FLIGHT_RECORDER_VALUE_LENGTH = MAX_DOMAIN_CONTROL_DS_PRESENTATION_LENGTH;
18
23
  export const MAX_FLIGHT_RECORDER_WINDOW_ID_LENGTH = 64;
19
24
  export const MAX_FLIGHT_RECORDER_WINDOW_REASON_LENGTH = 400;
20
25
  export const MAX_FLIGHT_RECORDER_JSON_DEPTH = 8;
@@ -45,18 +50,20 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_KEYS = Object.freeze([
45
50
  'observations',
46
51
  'approvedWindows',
47
52
  ]);
48
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS = Object.freeze([
53
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS = Object.freeze([
49
54
  'domain',
50
55
  'observedAt',
51
56
  'collectionDepth',
52
57
  'fields',
53
58
  ]);
54
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS = Object.freeze([
59
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS = Object.freeze(['domain', 'capturedAt', 'collectionDepth', 'fields']);
60
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS = Object.freeze([
55
61
  'id',
56
62
  'source',
57
63
  'state',
58
64
  'values',
59
65
  ]);
66
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS = Object.freeze([...PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS, 'observedAt']);
60
67
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_WINDOW_KEYS = Object.freeze([
61
68
  'id',
62
69
  'domain',
@@ -75,7 +82,7 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_ROOT_KEYS = Object.freeze([
75
82
  'summary',
76
83
  'limitations',
77
84
  ]);
78
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS = Object.freeze([
85
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS = Object.freeze([
79
86
  'id',
80
87
  'domain',
81
88
  'field',
@@ -88,11 +95,15 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS = Object.freeze([
88
95
  'approvedWindow',
89
96
  'explanation',
90
97
  ]);
91
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS = Object.freeze([
98
+ export const SOURCE_TIMED_FLIGHT_RECORDER_EVENT_KEYS = Object.freeze([...PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS, 'capturedAt']);
99
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS = Object.freeze([...SOURCE_TIMED_FLIGHT_RECORDER_EVENT_KEYS, 'collectionDepth', 'changeInterval']);
100
+ export const FLIGHT_RECORDER_CHANGE_INTERVAL_KEYS = Object.freeze(['after', 'by', 'incompleteObservations']);
101
+ export const HISTORICAL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS = Object.freeze([
92
102
  'id',
93
103
  'reason',
94
104
  ]);
95
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS = Object.freeze([
105
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS = Object.freeze([...HISTORICAL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS, 'startsAt', 'endsAt']);
106
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS = Object.freeze([
96
107
  'firstObservations',
97
108
  'observedChanges',
98
109
  'approvedChanges',
@@ -100,21 +111,30 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS = Object.freeze([
100
111
  'collectionChanges',
101
112
  'recoveredSources',
102
113
  ]);
103
- export const DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS = Object.freeze([
114
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS = Object.freeze([...PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS, 'incompleteFields']);
115
+ export const PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS = Object.freeze([
104
116
  'The flight recorder compares only supplied bounded observations and performs no collection or configuration change.',
105
117
  'Source fields remain separate. A collection failure, partial result, unsupported source, or missing field never becomes evidence that a prior value disappeared.',
106
118
  'Approved windows label expected timing but do not delete evidence or establish that a change was authorised, successful, safe, or complete.',
107
119
  'Observed changes can reflect publication lag or different collection conditions and require analyst review.',
108
120
  ]);
121
+ export const SOURCE_TIMED_FLIGHT_RECORDER_LIMITATIONS = Object.freeze([
122
+ ...PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS,
123
+ 'Capture time and source observation time remain separate. Unknown, conflicting or non-increasing source times cannot establish an observed change.',
124
+ ]);
125
+ export const DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS = Object.freeze([
126
+ ...SOURCE_TIMED_FLIGHT_RECORDER_LIMITATIONS,
127
+ 'A change interval is bounded by comparable complete source observations, not an exact change time. Incomplete observations inside it remain explicit. An approved window must contain the whole interval.',
128
+ ]);
109
129
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_COMPATIBILITY = defineSchemaCompatibility({
110
130
  id: 'cli.domain-control-flight-recorder-input',
111
131
  kind: 'cli_document',
112
132
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA,
113
133
  currentVersion: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
114
- supportedVersions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION],
134
+ supportedVersions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS,
115
135
  acceptsUnversionedLegacy: false,
116
136
  futureVersionBehavior: 'reject',
117
- migration: 'exact_current_only',
137
+ migration: 'read_only',
118
138
  writeSemantics: 'read_only',
119
139
  byteBudget: MAX_DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_BYTES,
120
140
  owner: 'packages/contracts/domain-control-flight-recorder.mts',
@@ -125,15 +145,18 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_COMPATIBILITY = defineSchemaCompatib
125
145
  kind: 'cli_document',
126
146
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA,
127
147
  currentVersion: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
128
- supportedVersions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION],
148
+ supportedVersions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS,
129
149
  acceptsUnversionedLegacy: false,
130
150
  futureVersionBehavior: 'reject',
131
- migration: 'exact_current_only',
151
+ migration: 'read_only',
132
152
  writeSemantics: 'read_only',
133
153
  byteBudget: MAX_DOMAIN_CONTROL_FLIGHT_RECORDER_OUTPUT_BYTES,
134
154
  owner: 'packages/contracts/domain-control-flight-recorder.mts',
135
155
  note: 'Offline first and last observed control history that preserves expected and unexpected changes.',
136
156
  });
157
+ const FLIGHT_INPUT_SHAPE_IDS = SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS.map((version) => `domain-control-flight-recorder.input.v${version}`);
158
+ const FLIGHT_DOCUMENT_SHAPE_IDS = SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS.map((version) => `domain-control-flight-recorder.document.v${version}`);
159
+ const CURRENT_FLIGHT_DOCUMENT_SHAPE_ID = `domain-control-flight-recorder.document.v${DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION}`;
137
160
  export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
138
161
  id: 'domain-control-flight-recorder',
139
162
  owner: 'packages/contracts/domain-control-flight-recorder.mts',
@@ -175,7 +198,11 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
175
198
  byteBudget: MAX_DOMAIN_CONTROL_FLIGHT_RECORDER_OUTPUT_BYTES,
176
199
  fixtureIds: ['domain-control-flight-recorder-v1'],
177
200
  },
178
- ],
201
+ ].flatMap((contract) => SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS.map((version) => ({
202
+ ...contract, version, lifecycle: version === DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? 'current' : 'legacy',
203
+ emitted: contract.emitted && version === DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
204
+ fixtureIds: contract.fixtureIds.map((id) => id.replace(/v\d+$/u, `v${version}`)),
205
+ }))),
179
206
  fixtures: [
180
207
  {
181
208
  id: 'domain-control-flight-recorder-input-v1',
@@ -184,7 +211,7 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
184
211
  sha256: '1fc4127a5885409d2ba76d40c1835a496767c6fe6d87f0545d8367d5f394a628',
185
212
  contentDigestSha256: null,
186
213
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA,
187
- version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
214
+ version: PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
188
215
  role: 'input',
189
216
  expectation: 'normalises_to_current_output',
190
217
  expectedOutputFixtureId: 'domain-control-flight-recorder-v1',
@@ -197,25 +224,42 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
197
224
  sha256: 'c35d43907bba7a7912f3151bc1a2ba37bb8f774c56a3bd5f690be262e842cf4c',
198
225
  contentDigestSha256: null,
199
226
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA,
200
- version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
227
+ version: PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION,
201
228
  role: 'current',
202
229
  expectation: 'accepted_exact',
203
230
  expectedOutputFixtureId: null,
204
231
  scope: 'repository',
205
232
  },
206
- ],
233
+ ].flatMap((fixture) => {
234
+ return [
235
+ { ...fixture, role: fixture.role === 'input' ? 'input' : 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
236
+ ...[2, DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION].map(version => {
237
+ const id = fixture.id.replace(/v\d+$/u, `v${version}`);
238
+ const content = version === 2
239
+ ? fixture.role === 'input'
240
+ ? { bytes: 2108, sha256: '6998ea864355dd0802b3b6f2c4905f8c84136ad0d4ac9cad1a0fd63dca523b60' }
241
+ : { bytes: 4649, sha256: '8f3168d101291166f34cede351bc176a934e7997920cd8c22ec00d642ec000df' }
242
+ : fixture.role === 'input'
243
+ ? { bytes: 2108, sha256: '3d9b91dfd34754482047cde64d6343676ec4747267677fcbcc989a65fbd9a6c6' }
244
+ : { bytes: 5597, sha256: 'ab6a82cfecfb8238a72fbe2dcd4a68a1fd888990e5070eff9d98a337796624d6' };
245
+ return { ...fixture, ...content, id, path: `test/fixtures/${id}.json`, version,
246
+ role: fixture.role === 'input' ? 'input' : version === DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? 'current' : 'historical',
247
+ expectation: version === DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? fixture.expectation : 'accepted_exact',
248
+ expectedOutputFixtureId: version === DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? fixture.expectedOutputFixtureId?.replace(/v\d+$/u, `v${version}`) ?? null : null };
249
+ }),
250
+ ];
251
+ }),
207
252
  metadata: {
208
- metadataVersion: 2,
209
253
  enforcement: 'declarative_only',
210
- shapes: [
254
+ shapes: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS.flatMap((version) => [
211
255
  {
212
- id: 'domain-control-flight-recorder.input.v1',
256
+ id: `domain-control-flight-recorder.input.v${version}`,
213
257
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA,
214
- versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION],
258
+ versions: [version],
215
259
  objects: [
216
260
  { path: '$', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_KEYS, optionalKeys: [], unknownKeys: 'reject' },
217
- { path: '$.observations[]', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS, optionalKeys: [], unknownKeys: 'reject' },
218
- { path: '$.observations[].fields[]', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS, optionalKeys: [], unknownKeys: 'reject' },
261
+ { path: '$.observations[]', requiredKeys: version === PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS : DOMAIN_CONTROL_FLIGHT_RECORDER_OBSERVATION_KEYS, optionalKeys: [], unknownKeys: 'reject' },
262
+ { path: '$.observations[].fields[]', requiredKeys: version === PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS : DOMAIN_CONTROL_FLIGHT_RECORDER_FIELD_KEYS, optionalKeys: [], unknownKeys: 'reject' },
219
263
  { path: '$.approvedWindows[]', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_WINDOW_KEYS, optionalKeys: [], unknownKeys: 'reject' },
220
264
  ],
221
265
  fixedArrays: [],
@@ -223,20 +267,21 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
223
267
  target: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
224
268
  },
225
269
  {
226
- id: 'domain-control-flight-recorder.document.v1',
270
+ id: `domain-control-flight-recorder.document.v${version}`,
227
271
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA,
228
- versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION],
272
+ versions: [version],
229
273
  objects: [
230
274
  { path: '$', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_ROOT_KEYS, optionalKeys: [], unknownKeys: 'reject' },
231
- { path: '$.events[]', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS, optionalKeys: [], unknownKeys: 'reject' },
232
- { path: '$.events[].approvedWindow', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS, optionalKeys: [], unknownKeys: 'reject' },
233
- { path: '$.summary', requiredKeys: DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS, optionalKeys: [], unknownKeys: 'reject' },
275
+ { path: '$.events[]', requiredKeys: version === 1 ? PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS : version === 2 ? SOURCE_TIMED_FLIGHT_RECORDER_EVENT_KEYS : DOMAIN_CONTROL_FLIGHT_RECORDER_EVENT_KEYS, optionalKeys: [], unknownKeys: 'reject' },
276
+ { path: '$.events[].approvedWindow', requiredKeys: version >= 3 ? DOMAIN_CONTROL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS : HISTORICAL_FLIGHT_RECORDER_APPROVED_WINDOW_KEYS, optionalKeys: [], unknownKeys: 'reject' },
277
+ ...(version >= 3 ? [{ path: '$.events[].changeInterval', requiredKeys: FLIGHT_RECORDER_CHANGE_INTERVAL_KEYS, optionalKeys: [], unknownKeys: 'reject' }] : []),
278
+ { path: '$.summary', requiredKeys: version === PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION ? PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS : DOMAIN_CONTROL_FLIGHT_RECORDER_SUMMARY_KEYS, optionalKeys: [], unknownKeys: 'reject' },
234
279
  ],
235
- fixedArrays: [{ path: '$.limitations', values: DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS }],
280
+ fixedArrays: [{ path: '$.limitations', values: version === 1 ? PUBLIC_DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS : version === 2 ? SOURCE_TIMED_FLIGHT_RECORDER_LIMITATIONS : DOMAIN_CONTROL_FLIGHT_RECORDER_LIMITATIONS }],
236
281
  normalisation: 'preserve_document',
237
282
  target: null,
238
283
  },
239
- ],
284
+ ]),
240
285
  boundProfiles: [
241
286
  {
242
287
  id: 'domain-control-flight-recorder.input-wire.v1',
@@ -248,7 +293,7 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
248
293
  { id: 'observation-fields', path: '$.observations[].fields', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_FIELDS, handling: 'reject' },
249
294
  { id: 'observation-unique-fields', path: '$.observations[].fields', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_UNIQUE_FIELDS, handling: 'reject' },
250
295
  { id: 'field-input-values', path: '$.observations[].fields[].values', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_INPUT_VALUES, handling: 'reject' },
251
- { id: 'field-values', path: '$.observations[].fields[].values', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_VALUES, handling: 'truncate' },
296
+ { id: 'field-values', path: '$.observations[].fields[].values', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_VALUES, handling: 'reject' },
252
297
  { id: 'field-source', path: '$.observations[].fields[].source', phase: 'pre_accumulation', unit: 'characters', minimum: 1, maximum: MAX_FLIGHT_RECORDER_SOURCE_LENGTH, handling: 'reject' },
253
298
  { id: 'field-value-text', path: '$.observations[].fields[].values[]', phase: 'pre_accumulation', unit: 'characters', minimum: 1, maximum: MAX_FLIGHT_RECORDER_VALUE_LENGTH, handling: 'reject' },
254
299
  { id: 'approved-windows', path: '$.approvedWindows', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_FLIGHT_RECORDER_WINDOWS, handling: 'reject' },
@@ -294,7 +339,7 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
294
339
  {
295
340
  id: 'domain-control-flight-recorder.json.v1',
296
341
  schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA,
297
- versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION],
342
+ versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS,
298
343
  mediaType: 'application/json',
299
344
  encoding: 'utf-8',
300
345
  bom: false,
@@ -353,13 +398,22 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
353
398
  },
354
399
  ],
355
400
  consumerEdges: [
401
+ {
402
+ id: 'domain-control-flight-recorder.node-validate', plane: 'node', operation: 'validate-document',
403
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
404
+ emittedContract: null, shapeIds: FLIGHT_DOCUMENT_SHAPE_IDS,
405
+ boundProfileIds: ['domain-control-flight-recorder.output-wire.v1'],
406
+ hookIds: ['domain-control-flight-recorder.node.validate-document'], serialisationProfileId: null,
407
+ privacyProfileId: 'domain-control-flight-recorder.sensitive.v1', expiryPolicyId: 'domain-control-flight-recorder.expiry-not-applicable.v1',
408
+ requestMode: 'none', retentionEffect: 'transient_report', bindingState: 'declared_unenforced', policyState: 'current',
409
+ },
356
410
  {
357
411
  id: 'domain-control-flight-recorder.node-build',
358
412
  plane: 'node',
359
413
  operation: 'review',
360
- acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION], mode: 'direct' }],
414
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
361
415
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
362
- shapeIds: ['domain-control-flight-recorder.input.v1', 'domain-control-flight-recorder.document.v1'],
416
+ shapeIds: [...FLIGHT_INPUT_SHAPE_IDS, CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
363
417
  boundProfileIds: ['domain-control-flight-recorder.input-wire.v1', 'domain-control-flight-recorder.output-wire.v1'],
364
418
  hookIds: ['domain-control-flight-recorder.node.build'],
365
419
  serialisationProfileId: null,
@@ -374,9 +428,9 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
374
428
  id: 'domain-control-flight-recorder.cli-json-stdout',
375
429
  plane: 'cli',
376
430
  operation: 'review-json-stdout',
377
- acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION], mode: 'direct' }],
431
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
378
432
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
379
- shapeIds: ['domain-control-flight-recorder.input.v1', 'domain-control-flight-recorder.document.v1'],
433
+ shapeIds: [...FLIGHT_INPUT_SHAPE_IDS, CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
380
434
  boundProfileIds: ['domain-control-flight-recorder.input-wire.v1', 'domain-control-flight-recorder.output-wire.v1', 'domain-control-flight-recorder.cli-command.v1'],
381
435
  hookIds: ['domain-control-flight-recorder.node.build', 'domain-control-flight-recorder.node.serialise-json'],
382
436
  serialisationProfileId: 'domain-control-flight-recorder.json.v1',
@@ -391,9 +445,9 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
391
445
  id: 'domain-control-flight-recorder.cli-terminal-stdout',
392
446
  plane: 'cli',
393
447
  operation: 'review-terminal-stdout',
394
- acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION], mode: 'direct' }],
448
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
395
449
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
396
- shapeIds: ['domain-control-flight-recorder.input.v1', 'domain-control-flight-recorder.document.v1'],
450
+ shapeIds: [...FLIGHT_INPUT_SHAPE_IDS, CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
397
451
  boundProfileIds: ['domain-control-flight-recorder.input-wire.v1', 'domain-control-flight-recorder.output-wire.v1', 'domain-control-flight-recorder.cli-command.v1'],
398
452
  hookIds: ['domain-control-flight-recorder.node.build', 'domain-control-flight-recorder.node.format-terminal'],
399
453
  serialisationProfileId: null,
@@ -408,9 +462,9 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
408
462
  id: 'domain-control-flight-recorder.cli-json-file',
409
463
  plane: 'cli',
410
464
  operation: 'review-json-file',
411
- acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION], mode: 'direct' }],
465
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
412
466
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
413
- shapeIds: ['domain-control-flight-recorder.input.v1', 'domain-control-flight-recorder.document.v1'],
467
+ shapeIds: [...FLIGHT_INPUT_SHAPE_IDS, CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
414
468
  boundProfileIds: ['domain-control-flight-recorder.input-wire.v1', 'domain-control-flight-recorder.output-wire.v1', 'domain-control-flight-recorder.cli-command.v1'],
415
469
  hookIds: ['domain-control-flight-recorder.node.build', 'domain-control-flight-recorder.node.serialise-json'],
416
470
  serialisationProfileId: 'domain-control-flight-recorder.json.v1',
@@ -425,9 +479,9 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
425
479
  id: 'domain-control-flight-recorder.cli-terminal-file',
426
480
  plane: 'cli',
427
481
  operation: 'review-terminal-file',
428
- acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: [DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION], mode: 'direct' }],
482
+ acceptedContracts: [{ schema: DOMAIN_CONTROL_FLIGHT_RECORDER_INPUT_SCHEMA, versions: SUPPORTED_DOMAIN_CONTROL_FLIGHT_RECORDER_VERSIONS, mode: 'direct' }],
429
483
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
430
- shapeIds: ['domain-control-flight-recorder.input.v1', 'domain-control-flight-recorder.document.v1'],
484
+ shapeIds: [...FLIGHT_INPUT_SHAPE_IDS, CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
431
485
  boundProfileIds: ['domain-control-flight-recorder.input-wire.v1', 'domain-control-flight-recorder.output-wire.v1', 'domain-control-flight-recorder.cli-command.v1'],
432
486
  hookIds: ['domain-control-flight-recorder.node.build', 'domain-control-flight-recorder.node.format-terminal'],
433
487
  serialisationProfileId: null,
@@ -444,7 +498,7 @@ export const DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA_LIFECYCLE = defineSchemaLifec
444
498
  operation: 'embed-after-current-manifest-bounded-passive-monitor',
445
499
  acceptedContracts: [],
446
500
  emittedContract: { schema: DOMAIN_CONTROL_FLIGHT_RECORDER_SCHEMA, version: DOMAIN_CONTROL_FLIGHT_RECORDER_VERSION },
447
- shapeIds: ['domain-control-flight-recorder.document.v1'],
501
+ shapeIds: [CURRENT_FLIGHT_DOCUMENT_SHAPE_ID],
448
502
  boundProfileIds: ['domain-control-flight-recorder.output-wire.v1', 'domain-control-flight-recorder.monitor-action.v1'],
449
503
  hookIds: ['domain-control-flight-recorder.node.validate-document', 'domain-control-flight-recorder.cli.monitor'],
450
504
  serialisationProfileId: null,