@slicedearth/whoisleuth-cli 2.5.1 → 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.
- package/DISCLOSURE +1 -1
- package/cli/artifact-validation/case-response.mjs +51 -8
- package/cli/artifact-validation/lookup-evidence.mjs +15 -1
- package/cli/artifact-validation/signed-review.mjs +2 -51
- package/cli/artifact-verify.mjs +9 -2
- package/cli/bulk-command-runner.mjs +4 -6
- package/cli/case-command.mjs +79 -3
- package/cli/case-pack.mjs +7 -2
- package/cli/command-definition.mjs +2 -1
- package/cli/discovery-scan-command-runner.mjs +4 -6
- package/cli/domain-feed.mjs +61 -0
- package/cli/formatters/json.mjs +1 -13
- package/cli/indicator-set-command.mjs +1 -2
- package/cli/intake-command.mjs +43 -3
- package/cli/investigation-artifacts.mjs +2 -3
- package/cli/investigation-package-review.mjs +2 -0
- package/cli/local-mmdb-review.mjs +27 -4
- package/cli/lookup-command-runner.mjs +1 -0
- package/cli/offline-evidence-review.mjs +51 -5
- package/cli/review-arguments.mjs +3 -2
- package/cli/review-command-definitions.mjs +14 -8
- package/cli/review-command-runner.mjs +6 -3
- package/cli/risk-calibration.mjs +6 -4
- package/cli/selected-input-worker.mjs +12 -2
- package/cli/support-command-runner.mjs +3 -3
- package/cli/watchlist-review.mjs +43 -0
- package/cli/workflow-arguments.mjs +14 -0
- package/cli/workflow-command-definitions.mjs +26 -1
- package/cli/workflow-command-runner.mjs +32 -0
- package/docs/cli.md +99 -2
- package/docs/contextual-reviews.md +28 -5
- package/docs/infrastructure-observations.md +126 -0
- package/docs/offline-intake-context.md +213 -0
- package/lib/credential-form-attribution.mjs +136 -0
- package/lib/credential-surface-profile.mjs +6 -2
- package/lib/dns-delegation-health.mjs +23 -7
- package/lib/dns-intelligence.mjs +18 -4
- package/lib/domain-posture-analysis.mjs +53 -2
- package/lib/domain-posture-parsers.mjs +9 -0
- package/lib/domain-posture.mjs +29 -10
- package/lib/evidence-export-privacy.mjs +5 -2
- package/lib/evidence-report.mjs +1 -0
- package/lib/favicon.mjs +13 -4
- package/lib/html-signals.mjs +6 -0
- package/lib/lookup-child-profile-contract.mjs +28 -11
- package/lib/lookup-response-contract.mjs +1 -0
- package/lib/operation-budget.mjs +4 -0
- package/lib/service-binding-dns.mjs +19 -2
- package/lib/sslbl-certificates.generated.mjs +138 -137
- package/lib/static-html-analysis.mjs +32 -4
- package/lib/technology-evidence-role.mjs +1 -51
- package/lib/tls-intelligence.mjs +30 -5
- package/lib/website-enrichment.mjs +39 -23
- package/lib/whois-chain.mjs +12 -3
- package/lib/whois-common-formats.mjs +3 -1
- package/lib/whois-contacts.mjs +13 -2
- package/package.json +7 -5
- package/packages/analysis/risk-scoring.mjs +12 -9
- package/packages/cases/case-containment-handoff.mjs +195 -0
- package/packages/cases/case-evidence-links.mjs +16 -0
- package/packages/cases/case-evidence-model.mjs +14 -3
- package/packages/cases/case-object-coverage.mjs +33 -0
- package/packages/cases/case-packet-correction.mjs +106 -0
- package/packages/cases/case-recheck-model.mjs +35 -5
- package/packages/cases/case-record-operations.mjs +74 -9
- package/packages/cases/case-record-projection.mjs +15 -3
- package/packages/cases/case-record-version-input.mjs +23 -1
- package/packages/cases/case-report.mjs +30 -0
- package/packages/cases/case-requested-evidence.mjs +1 -1
- package/packages/cases/case-response-actions.mjs +57 -1
- package/packages/cases/case-response-model.mjs +7 -0
- package/packages/cases/case-response-object.mjs +119 -0
- package/packages/cases/case-response-outcomes.mjs +81 -14
- package/packages/cases/case-response-packet-render.mjs +22 -3
- package/packages/cases/case-response-packet.mjs +30 -2
- package/packages/cases/case-response-review-inputs.mjs +48 -7
- package/packages/cases/case-workflow-metadata.mjs +1 -9
- package/packages/contracts/analyst-interchange.mjs +7 -5
- package/packages/contracts/candidate-watch-review.mjs +54 -0
- package/packages/contracts/case-portability.mjs +260 -42
- package/packages/contracts/cli-command-semantics.mjs +3 -0
- package/packages/contracts/context-review.mjs +2 -1
- package/packages/contracts/external-observation-interchange.mjs +96 -28
- package/packages/contracts/lookup-evidence.mjs +3 -2
- package/packages/contracts/message-intake.mjs +7 -1
- package/packages/contracts/risk-calibration.mjs +44 -29
- package/packages/contracts/schema-lifecycle.mjs +3 -1
- package/packages/contracts/web-capture.mjs +1 -1
- package/packages/contracts/workspace-portability.mjs +86 -16
- package/packages/evidence/collection-quality.mjs +1 -1
- package/packages/evidence/credential-form-attribution.mjs +60 -0
- package/packages/evidence/image-regions.mjs +15 -0
- package/packages/evidence/record-identity.mjs +60 -16
- package/packages/evidence/technology-evidence-role.mjs +51 -0
- package/packages/interchange/external-findings-import.mjs +32 -17
- package/packages/interchange/json-output.mjs +14 -0
- package/packages/interchange/managed-indicator-export.mjs +3 -2
- package/packages/interchange/managed-indicator-set.mjs +13 -0
- package/packages/investigation/acquisition-decision-packet.mjs +78 -0
- package/packages/investigation/context-review.mjs +3 -3
- package/packages/investigation/document-intake.mjs +9 -3
- package/packages/investigation/domain-history-review.mjs +43 -11
- package/packages/investigation/domain-transition-review.mjs +2 -0
- package/packages/investigation/infrastructure-observation.mjs +234 -0
- package/packages/investigation/intake-context.mjs +284 -0
- package/packages/investigation/intake-indicators.mjs +116 -0
- package/packages/investigation/intake-phones.mjs +155 -0
- package/packages/investigation/intake-report.mjs +2 -1
- package/packages/investigation/investigation-manifest.mjs +33 -7
- package/packages/investigation/link-intake.mjs +38 -8
- package/packages/investigation/message-intake.mjs +55 -15
- package/packages/monitoring/domain-feed.mjs +321 -0
- package/packages/workspace/brand-candidate-workflow.mjs +351 -0
- package/packages/workspace/brand-keyword-campaign.mjs +231 -0
- package/packages/workspace/brand-profile-model.mjs +46 -2
- package/packages/workspace/bulk-session-model.mjs +4 -0
- package/packages/workspace/candidate-watch-handoff.mjs +195 -0
- package/packages/workspace/detection-rule-model.mjs +10 -2
- package/packages/workspace/shortlist-model.mjs +10 -2
- package/packages/workspace/watchlist-history.mjs +31 -4
- package/packages/workspace/watchlist-store.mjs +136 -7
- package/third-party-notices.txt +29 -29
|
@@ -2,8 +2,8 @@ import { defineSchemaCompatibility } from "./schema-compatibility.mjs";
|
|
|
2
2
|
import { defineSchemaLifecycleFamily } from "./schema-lifecycle.mjs";
|
|
3
3
|
export const EXTERNAL_OBSERVATION_INTERCHANGE_CONTRACT_OWNER = 'packages/contracts/external-observation-interchange.mts';
|
|
4
4
|
export const EXTERNAL_FINDINGS_SCHEMA = 'whoisleuth.external-findings';
|
|
5
|
-
export const EXTERNAL_FINDINGS_VERSION =
|
|
6
|
-
export const SUPPORTED_EXTERNAL_FINDINGS_VERSIONS = Object.freeze([
|
|
5
|
+
export const EXTERNAL_FINDINGS_VERSION = 5;
|
|
6
|
+
export const SUPPORTED_EXTERNAL_FINDINGS_VERSIONS = Object.freeze([4, 5]);
|
|
7
7
|
export const MAX_EXTERNAL_FINDINGS_IMPORT_BYTES = 384 * 1024;
|
|
8
8
|
export const MAX_EXTERNAL_FINDINGS = 100;
|
|
9
9
|
export const MAX_EXTERNAL_FINDINGS_PER_DOMAIN = 20;
|
|
@@ -17,6 +17,19 @@ export const DNS_OBSERVATION_ROWS_SCHEMA = 'whoisleuth.dns-observation-rows';
|
|
|
17
17
|
export const CERTIFICATE_OBSERVATION_ROWS_SCHEMA = 'whoisleuth.certificate-observation-rows';
|
|
18
18
|
export const SUPPORTED_OBSERVATION_ROWS_VERSION = 1;
|
|
19
19
|
export const MAX_CONVERSION_INPUT_ROWS = MAX_EXTERNAL_FINDINGS * 4;
|
|
20
|
+
export const INFRASTRUCTURE_OBSERVATION_SCHEMA = 'whoisleuth.infrastructure-observation';
|
|
21
|
+
export const INFRASTRUCTURE_OBSERVATION_VERSION = 1;
|
|
22
|
+
export const MAX_INFRASTRUCTURE_OBSERVATION_BYTES = 128 * 1024;
|
|
23
|
+
export const MAX_INFRASTRUCTURE_HOSTS = 128;
|
|
24
|
+
export const MAX_INFRASTRUCTURE_DNS_ROWS = 512;
|
|
25
|
+
export const MAX_INFRASTRUCTURE_CERTIFICATES = 32;
|
|
26
|
+
export const MAX_INFRASTRUCTURE_ROLES = 128;
|
|
27
|
+
export const MAX_INFRASTRUCTURE_SOURCES = 16;
|
|
28
|
+
export const MAX_INFRASTRUCTURE_LIMITATIONS = 12;
|
|
29
|
+
export const INFRASTRUCTURE_DNS_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR'];
|
|
30
|
+
export const INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA = 'whoisleuth.infrastructure-comparison.input';
|
|
31
|
+
export const INFRASTRUCTURE_COMPARISON_INPUT_VERSION = 1;
|
|
32
|
+
export const MAX_INFRASTRUCTURE_COMPARISON_INPUT_BYTES = 2 * MAX_INFRASTRUCTURE_OBSERVATION_BYTES + 1_024;
|
|
20
33
|
export const EXTERNAL_OBSERVATION_INTERCHANGE_COMPATIBILITY_FACADES = Object.freeze([
|
|
21
34
|
['frontend/src/lib/analysis/external-findings-import.ts', 'packages/interchange/external-findings-import.mts'],
|
|
22
35
|
['frontend/src/lib/analysis/external-findings-converters.ts', 'packages/interchange/external-findings-converters.mts'],
|
|
@@ -24,9 +37,9 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_COMPATIBILITY_FACADES = Object.fre
|
|
|
24
37
|
export const EXTERNAL_FINDINGS_COMPATIBILITY = defineSchemaCompatibility({
|
|
25
38
|
id: 'export.external-findings', kind: 'export', schema: EXTERNAL_FINDINGS_SCHEMA,
|
|
26
39
|
currentVersion: EXTERNAL_FINDINGS_VERSION, supportedVersions: SUPPORTED_EXTERNAL_FINDINGS_VERSIONS,
|
|
27
|
-
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: '
|
|
40
|
+
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'none', writeSemantics: 'non_destructive_merge',
|
|
28
41
|
byteBudget: MAX_EXTERNAL_FINDINGS_IMPORT_BYTES, owner: EXTERNAL_OBSERVATION_INTERCHANGE_CONTRACT_OWNER,
|
|
29
|
-
note: 'Strict local findings import.
|
|
42
|
+
note: 'Strict local findings import. Historical version 4 is preserved exactly; version 5 adds an optional exact source-qualified infrastructure snapshot. No collection is initiated.',
|
|
30
43
|
});
|
|
31
44
|
export const EXTERNAL_FINDING_ROWS_COMPATIBILITY = defineSchemaCompatibility({
|
|
32
45
|
id: 'import.external-finding-rows', kind: 'export', schema: EXTERNAL_FINDING_ROWS_SCHEMA,
|
|
@@ -62,17 +75,26 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_COMPATIBILITY = Object.freeze([
|
|
|
62
75
|
DOMAIN_OBSERVATION_ROWS_COMPATIBILITY,
|
|
63
76
|
DNS_OBSERVATION_ROWS_COMPATIBILITY,
|
|
64
77
|
CERTIFICATE_OBSERVATION_ROWS_COMPATIBILITY,
|
|
78
|
+
defineSchemaCompatibility({ id: 'export.infrastructure-observation', kind: 'export', schema: INFRASTRUCTURE_OBSERVATION_SCHEMA, currentVersion: 1, supportedVersions: [1], acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'exact_current_only', writeSemantics: 'read_only', byteBudget: MAX_INFRASTRUCTURE_OBSERVATION_BYTES, owner: EXTERNAL_OBSERVATION_INTERCHANGE_CONTRACT_OWNER, note: 'Exact source-qualified selected infrastructure evidence retained through existing Case pins. Wildcards, DNS outcomes and independent provider roles remain distinct.' }),
|
|
79
|
+
defineSchemaCompatibility({ id: 'cli.infrastructure-comparison-input', kind: 'cli_document', schema: INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA, currentVersion: 1, supportedVersions: [1], acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'read_only', writeSemantics: 'read_only', byteBudget: MAX_INFRASTRUCTURE_COMPARISON_INPUT_BYTES, owner: EXTERNAL_OBSERVATION_INTERCHANGE_CONTRACT_OWNER, note: 'An explicit earlier/later snapshot pair reviewed offline without collection, persistence or current absence claims.' }),
|
|
65
80
|
]);
|
|
66
81
|
const EXTERNAL_INTERCHANGE_FIXTURES = Object.freeze([
|
|
67
|
-
{ id: 'external-findings-v4', path: 'test/fixtures/external-observation-interchange/external-findings-v4.json', bytes: 634, sha256: 'ceab916e1dcf99704c94e1b0cd82f5a061f138ae6a07ce8335273080c73b7624', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: '
|
|
68
|
-
{ id: 'external-finding-rows-v1', path: 'test/fixtures/external-observation-interchange/external-finding-rows-v1.json', bytes: 435, sha256: '09048325d801fdc837134580fd887cacde28744c9f87a43afc388c96117a4659', schema: EXTERNAL_FINDING_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'external-finding-rows-v1-output' },
|
|
69
|
-
{ id: 'external-finding-rows-v1-output', path: 'test/fixtures/external-observation-interchange/external-finding-rows-v1-output.json', bytes: 581, sha256: '7f84a9f6177d3245acd6fc21275276694fbe9e8cd94922b1e6997a73afa3149a', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: '
|
|
70
|
-
{ id: 'domain-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/domain-observation-rows-v1.json', bytes: 390, sha256: '2f95ab21e57e1a6aaab03cea75a4d58fd9e1234ba87f5268a899b23103359474', schema: DOMAIN_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'domain-observation-rows-v1-output' },
|
|
71
|
-
{ id: 'domain-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/domain-observation-rows-v1-output.json', bytes: 1_027, sha256: 'bba949308e9bb5b58bf5611d6dec23f074979522627631948cffc2f0056ac817', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: '
|
|
72
|
-
{ id: 'dns-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/dns-observation-rows-v1.json', bytes: 369, sha256: 'afb1808a8a81339a1801d337259c19c77ed957583b4ae06579b38ea6a8f68ed1', schema: DNS_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'dns-observation-rows-v1-output' },
|
|
73
|
-
{ id: 'dns-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/dns-observation-rows-v1-output.json', bytes: 988, sha256: '4c9a49b96181d2907eb95319d15975758823994fe029c051486f1cb6869221a0', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: '
|
|
74
|
-
{ id: 'certificate-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/certificate-observation-rows-v1.json', bytes: 515, sha256: '68363a5fe074b08a386dbc95a0993a2933ebcf05ba2f96148df632842d1c5869', schema: CERTIFICATE_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'certificate-observation-rows-v1-output' },
|
|
75
|
-
{ id: 'certificate-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/certificate-observation-rows-v1-output.json', bytes: 1_244, sha256: '6c484601b872f10bfdb7d9519d4b216f14ef277e7a429e4cc131154ad0e07652', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: '
|
|
82
|
+
{ id: 'external-findings-v4', path: 'test/fixtures/external-observation-interchange/external-findings-v4.json', bytes: 634, sha256: 'ceab916e1dcf99704c94e1b0cd82f5a061f138ae6a07ce8335273080c73b7624', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
83
|
+
{ id: 'external-finding-rows-v1', path: 'test/fixtures/external-observation-interchange/external-finding-rows-v1.json', bytes: 435, sha256: '09048325d801fdc837134580fd887cacde28744c9f87a43afc388c96117a4659', schema: EXTERNAL_FINDING_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'external-finding-rows-v1-output-v5' },
|
|
84
|
+
{ id: 'external-finding-rows-v1-output', path: 'test/fixtures/external-observation-interchange/external-finding-rows-v1-output.json', bytes: 581, sha256: '7f84a9f6177d3245acd6fc21275276694fbe9e8cd94922b1e6997a73afa3149a', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
85
|
+
{ id: 'domain-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/domain-observation-rows-v1.json', bytes: 390, sha256: '2f95ab21e57e1a6aaab03cea75a4d58fd9e1234ba87f5268a899b23103359474', schema: DOMAIN_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'domain-observation-rows-v1-output-v5' },
|
|
86
|
+
{ id: 'domain-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/domain-observation-rows-v1-output.json', bytes: 1_027, sha256: 'bba949308e9bb5b58bf5611d6dec23f074979522627631948cffc2f0056ac817', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
87
|
+
{ id: 'dns-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/dns-observation-rows-v1.json', bytes: 369, sha256: 'afb1808a8a81339a1801d337259c19c77ed957583b4ae06579b38ea6a8f68ed1', schema: DNS_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'dns-observation-rows-v1-output-v5' },
|
|
88
|
+
{ id: 'dns-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/dns-observation-rows-v1-output.json', bytes: 988, sha256: '4c9a49b96181d2907eb95319d15975758823994fe029c051486f1cb6869221a0', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
89
|
+
{ id: 'certificate-observation-rows-v1', path: 'test/fixtures/external-observation-interchange/certificate-observation-rows-v1.json', bytes: 515, sha256: '68363a5fe074b08a386dbc95a0993a2933ebcf05ba2f96148df632842d1c5869', schema: CERTIFICATE_OBSERVATION_ROWS_SCHEMA, version: 1, role: 'input', expectation: 'normalises_to_current_output', expectedOutputFixtureId: 'certificate-observation-rows-v1-output-v5' },
|
|
90
|
+
{ id: 'certificate-observation-rows-v1-output', path: 'test/fixtures/external-observation-interchange/certificate-observation-rows-v1-output.json', bytes: 1_244, sha256: '6c484601b872f10bfdb7d9519d4b216f14ef277e7a429e4cc131154ad0e07652', schema: EXTERNAL_FINDINGS_SCHEMA, version: 4, role: 'historical', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
91
|
+
{ id: 'external-finding-rows-v1-output-v5', path: 'test/fixtures/external-observation-interchange/external-finding-rows-v1-output-v5.json', bytes: 442, sha256: '9996be2b9d832fca9aa523a1a424148ef762483ab3923d35ca73e83cd16a8195', schema: EXTERNAL_FINDINGS_SCHEMA, version: 5, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
92
|
+
{ id: 'domain-observation-rows-v1-output-v5', path: 'test/fixtures/external-observation-interchange/domain-observation-rows-v1-output-v5.json', bytes: 771, sha256: 'd375353576b5990e835d53c14bf7fa5adb5205191d3969478a69ec68b5e1291b', schema: EXTERNAL_FINDINGS_SCHEMA, version: 5, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
93
|
+
{ id: 'dns-observation-rows-v1-output-v5', path: 'test/fixtures/external-observation-interchange/dns-observation-rows-v1-output-v5.json', bytes: 732, sha256: '532ff6ac9e9255f14105eb0a0286434fadb94f6d7397f0fb96007ebb6b7d1522', schema: EXTERNAL_FINDINGS_SCHEMA, version: 5, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
94
|
+
{ id: 'certificate-observation-rows-v1-output-v5', path: 'test/fixtures/external-observation-interchange/certificate-observation-rows-v1-output-v5.json', bytes: 988, sha256: '09904df103f83f64616556e653fa14c6f2f1dc392b1f75a85fd3099680840e37', schema: EXTERNAL_FINDINGS_SCHEMA, version: 5, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
95
|
+
{ id: 'external-findings-v5', path: 'test/fixtures/external-observation-interchange/external-findings-v5.json', bytes: 3871, sha256: 'debd062c2d951d22c06c29bb076529fa69a2769b8bae7269ce3884550fb55ba3', schema: EXTERNAL_FINDINGS_SCHEMA, version: 5, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
96
|
+
{ id: 'infrastructure-comparison-input-v1', path: 'test/fixtures/infrastructure-observations/infrastructure-comparison-input-v1.json', bytes: 6284, sha256: 'ef0022faf29586774bd1b2de1f95eb3839d382e424c7b3d446e4dc1058437104', schema: INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA, version: 1, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
97
|
+
{ id: 'infrastructure-observation-v1', path: 'test/fixtures/infrastructure-observations/infrastructure-observation-v1.json', bytes: 3430, sha256: '1b76e43e5d5c889654faf12114217994c5cbd3a378685e7f9b9d18ebdde801f7', schema: INFRASTRUCTURE_OBSERVATION_SCHEMA, version: 1, role: 'current', expectation: 'accepted_exact', expectedOutputFixtureId: null },
|
|
76
98
|
].map((fixture) => Object.freeze({
|
|
77
99
|
...fixture,
|
|
78
100
|
contentDigestSha256: null,
|
|
@@ -84,6 +106,7 @@ function externalFixtureIds(schema, version) {
|
|
|
84
106
|
.map((fixture) => fixture.id));
|
|
85
107
|
}
|
|
86
108
|
const EXTERNAL_INTERCHANGE_CONTRACTS = Object.freeze([
|
|
109
|
+
...[['export.infrastructure-observation', INFRASTRUCTURE_OBSERVATION_SCHEMA, true, MAX_INFRASTRUCTURE_OBSERVATION_BYTES], ['cli.infrastructure-comparison-input', INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA, false, MAX_INFRASTRUCTURE_COMPARISON_INPUT_BYTES]].map(([compatibilityId, schema, emitted, byteBudget]) => Object.freeze({ compatibilityId, schema, version: 1, role: 'document', lifecycle: 'current', readable: true, emitted, exactKeys: true, extensionPolicy: 'reject', futureVersionBehaviour: 'reject', migrationTarget: null, canonicalisation: null, byteBudget, fixtureIds: externalFixtureIds(schema, 1) })),
|
|
87
110
|
...SUPPORTED_EXTERNAL_FINDINGS_VERSIONS.map((version) => Object.freeze({
|
|
88
111
|
compatibilityId: EXTERNAL_FINDINGS_COMPATIBILITY.id,
|
|
89
112
|
schema: EXTERNAL_FINDINGS_SCHEMA,
|
|
@@ -95,7 +118,7 @@ const EXTERNAL_INTERCHANGE_CONTRACTS = Object.freeze([
|
|
|
95
118
|
exactKeys: true,
|
|
96
119
|
extensionPolicy: 'reject',
|
|
97
120
|
futureVersionBehaviour: 'reject',
|
|
98
|
-
migrationTarget:
|
|
121
|
+
migrationTarget: null,
|
|
99
122
|
canonicalisation: null,
|
|
100
123
|
byteBudget: MAX_EXTERNAL_FINDINGS_IMPORT_BYTES,
|
|
101
124
|
fixtureIds: externalFixtureIds(EXTERNAL_FINDINGS_SCHEMA, version),
|
|
@@ -151,18 +174,38 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_LIFECYCLE_FAMILY = defineSchemaLif
|
|
|
151
174
|
metadata: {
|
|
152
175
|
enforcement: 'declarative_only',
|
|
153
176
|
shapes: [
|
|
154
|
-
externalShape('external-interchange.findings.v4', EXTERNAL_FINDINGS_SCHEMA, [
|
|
177
|
+
externalShape('external-interchange.findings.v4', EXTERNAL_FINDINGS_SCHEMA, [4], ['schema', 'schemaVersion', 'source', 'findings'], 'preserve_document'),
|
|
178
|
+
externalShape('external-interchange.findings.v5', EXTERNAL_FINDINGS_SCHEMA, [5], ['schema', 'schemaVersion', 'source', 'findings'], 'preserve_document'),
|
|
179
|
+
externalShape('external-interchange.infrastructure.v1', INFRASTRUCTURE_OBSERVATION_SCHEMA, [1], ['schema', 'version', 'id', 'target', 'observedAt', 'mode', 'scope', 'coverage', 'sources', 'dns', 'certificates', 'roles', 'limitations'], 'preserve_document'),
|
|
180
|
+
externalShape('external-interchange.infrastructure-comparison.v1', INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA, [1], ['schema', 'version', 'earlier', 'later'], 'preserve_document'),
|
|
155
181
|
externalShape('external-interchange.finding-rows.v1', EXTERNAL_FINDING_ROWS_SCHEMA, [1], ['schema', 'schemaVersion', 'source', 'rows'], 'input_to_current'),
|
|
156
182
|
externalShape('external-interchange.domain-rows.v1', DOMAIN_OBSERVATION_ROWS_SCHEMA, [1], ['schema', 'schemaVersion', 'source', 'observations'], 'input_to_current'),
|
|
157
183
|
externalShape('external-interchange.dns-rows.v1', DNS_OBSERVATION_ROWS_SCHEMA, [1], ['schema', 'schemaVersion', 'source', 'observations'], 'input_to_current'),
|
|
158
184
|
externalShape('external-interchange.certificate-rows.v1', CERTIFICATE_OBSERVATION_ROWS_SCHEMA, [1], ['schema', 'schemaVersion', 'source', 'observations'], 'input_to_current'),
|
|
159
185
|
],
|
|
160
|
-
boundProfiles: [{ id: 'external-interchange.
|
|
186
|
+
boundProfiles: [{ id: 'external-interchange.infrastructure.bounds', bounds: [
|
|
187
|
+
{ id: 'raw-bytes', path: '$', phase: 'raw_intake', unit: 'bytes', minimum: 1, maximum: MAX_INFRASTRUCTURE_OBSERVATION_BYTES, handling: 'reject' },
|
|
188
|
+
{ id: 'serialised-bytes', path: '$', phase: 'serialised', unit: 'bytes', minimum: 1, maximum: MAX_INFRASTRUCTURE_OBSERVATION_BYTES, handling: 'reject' },
|
|
189
|
+
{ id: 'hostnames', path: 'scope.hostnames', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_INFRASTRUCTURE_HOSTS, handling: 'reject' },
|
|
190
|
+
{ id: 'dns-rows', path: 'dns', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_INFRASTRUCTURE_DNS_ROWS, handling: 'reject' },
|
|
191
|
+
{ id: 'certificate-rows', path: 'certificates', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_INFRASTRUCTURE_CERTIFICATES, handling: 'reject' },
|
|
192
|
+
{ id: 'role-rows', path: 'roles', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_INFRASTRUCTURE_ROLES, handling: 'reject' },
|
|
193
|
+
{ id: 'sources', path: 'sources', phase: 'pre_accumulation', unit: 'items', minimum: 1, maximum: MAX_INFRASTRUCTURE_SOURCES, handling: 'reject' },
|
|
194
|
+
{ id: 'dns-types', path: 'scope.dnsTypes', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: INFRASTRUCTURE_DNS_TYPES.length, handling: 'reject' },
|
|
195
|
+
{ id: 'limitations', path: 'limitations', phase: 'pre_accumulation', unit: 'items', minimum: 0, maximum: MAX_INFRASTRUCTURE_LIMITATIONS, handling: 'reject' },
|
|
196
|
+
] }, { id: 'external-interchange.infrastructure-comparison.bounds', bounds: [
|
|
197
|
+
{ id: 'raw-bytes', path: '$', phase: 'raw_intake', unit: 'bytes', minimum: 1, maximum: MAX_INFRASTRUCTURE_COMPARISON_INPUT_BYTES, handling: 'reject' },
|
|
198
|
+
{ id: 'serialised-bytes', path: '$', phase: 'serialised', unit: 'bytes', minimum: 1, maximum: MAX_INFRASTRUCTURE_COMPARISON_INPUT_BYTES, handling: 'reject' },
|
|
199
|
+
] }, { id: 'external-interchange.document.bounds', bounds: [
|
|
161
200
|
{ id: 'raw-bytes', path: '$', phase: 'raw_intake', unit: 'bytes', minimum: 1, maximum: MAX_EXTERNAL_FINDINGS_IMPORT_BYTES, handling: 'reject' },
|
|
162
201
|
{ id: 'serialised-bytes', path: '$', phase: 'serialised', unit: 'bytes', minimum: 1, maximum: MAX_EXTERNAL_FINDINGS_IMPORT_BYTES, handling: 'reject' },
|
|
163
202
|
{ id: 'rows', path: '$', phase: 'pre_accumulation', unit: 'items', minimum: 1, maximum: MAX_CONVERSION_INPUT_ROWS, handling: 'reject' },
|
|
164
203
|
] }],
|
|
165
204
|
hooks: [
|
|
205
|
+
{ id: 'external-interchange.infrastructure.read', role: 'normaliser', runtime: 'shared', module: 'packages/investigation/infrastructure-observation.mts', exportName: 'readInfrastructureObservation' },
|
|
206
|
+
{ id: 'external-interchange.infrastructure.serialise', role: 'serialiser', runtime: 'shared', module: 'packages/investigation/infrastructure-observation.mts', exportName: 'serialiseInfrastructureObservation' },
|
|
207
|
+
{ id: 'external-interchange.infrastructure.convert', role: 'normaliser', runtime: 'shared', module: 'packages/interchange/external-findings-converters.mts', exportName: 'convertInfrastructureObservation' },
|
|
208
|
+
{ id: 'external-interchange.infrastructure.compare', role: 'normaliser', runtime: 'cli', module: 'cli/offline-evidence-review.mts', exportName: 'buildOfflineEvidenceReview' },
|
|
166
209
|
{ id: 'external-interchange.findings.normalise', role: 'normaliser', runtime: 'shared', module: 'packages/interchange/external-findings-import.mts', exportName: 'parseExternalFindingsDocument' },
|
|
167
210
|
{ id: 'external-interchange.findings.serialise', role: 'serialiser', runtime: 'shared', module: 'packages/interchange/external-findings-import.mts', exportName: 'serializeExternalFindingsDocument' },
|
|
168
211
|
{ id: 'external-interchange.finding-rows.convert', role: 'normaliser', runtime: 'shared', module: 'packages/interchange/external-findings-converters.mts', exportName: 'convertExternalFindingRows' },
|
|
@@ -170,10 +213,15 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_LIFECYCLE_FAMILY = defineSchemaLif
|
|
|
170
213
|
{ id: 'external-interchange.findings.merge', role: 'merger', runtime: 'shared', module: 'packages/interchange/external-findings-import.mts', exportName: 'mergeExternalFindingsIntoCases' },
|
|
171
214
|
],
|
|
172
215
|
serialisationProfiles: [{
|
|
173
|
-
id: 'external-interchange.findings.json.
|
|
174
|
-
versions: [
|
|
175
|
-
indentSpaces:
|
|
216
|
+
id: 'external-interchange.findings.json.v5', schema: EXTERNAL_FINDINGS_SCHEMA,
|
|
217
|
+
versions: [5], mediaType: 'application/json', encoding: 'utf-8', bom: false,
|
|
218
|
+
indentSpaces: 0, terminalLf: true, propertyOrder: 'normalised_fixed', canonicalisation: null, integrity: 'none',
|
|
176
219
|
serializerHookId: 'external-interchange.findings.serialise', verifierHookIds: [],
|
|
220
|
+
}, {
|
|
221
|
+
id: 'external-interchange.infrastructure.json.v1', schema: INFRASTRUCTURE_OBSERVATION_SCHEMA,
|
|
222
|
+
versions: [1], mediaType: 'application/json', encoding: 'utf-8', bom: false,
|
|
223
|
+
indentSpaces: 0, terminalLf: true, propertyOrder: 'normalised_fixed', canonicalisation: null, integrity: 'none',
|
|
224
|
+
serializerHookId: 'external-interchange.infrastructure.serialise', verifierHookIds: [],
|
|
177
225
|
}],
|
|
178
226
|
privacyProfiles: [
|
|
179
227
|
{ id: 'external-interchange.privacy.transient', classification: 'analyst_authored_sensitive', projection: 'browser_import', includedCategories: ['source-attribution', 'bounded-observations', 'completeness', 'limitations'], excludedCategories: ['raw-upstream-payloads', 'expanded-contacts', 'credentials', 'cookies', 'query-bearing-urls'], notePolicy: 'discarded', retention: 'transient_report', network: 'none', sharingReview: 'required' },
|
|
@@ -181,22 +229,42 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_LIFECYCLE_FAMILY = defineSchemaLif
|
|
|
181
229
|
],
|
|
182
230
|
expiryProfiles: [{ id: 'external-interchange.expiry.not-applicable', field: null, anchor: null, handling: 'not_applicable', phase: 'not_applicable', maximumLifetimeDays: null }],
|
|
183
231
|
consumerEdges: [
|
|
232
|
+
{
|
|
233
|
+
id: 'external-interchange.consumer.infrastructure-read', plane: 'shared', operation: 'read-and-export-exact-infrastructure-snapshot',
|
|
234
|
+
acceptedContracts: [{ schema: INFRASTRUCTURE_OBSERVATION_SCHEMA, versions: [1], mode: 'direct' }], emittedContract: { schema: INFRASTRUCTURE_OBSERVATION_SCHEMA, version: 1 },
|
|
235
|
+
shapeIds: ['external-interchange.infrastructure.v1'], boundProfileIds: ['external-interchange.infrastructure.bounds'], hookIds: ['external-interchange.infrastructure.read', 'external-interchange.infrastructure.serialise'], serialisationProfileId: 'external-interchange.infrastructure.json.v1', privacyProfileId: 'external-interchange.privacy.transient', retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: 'external-interchange.consumer.infrastructure-convert', plane: 'shared', operation: 'convert-exact-snapshot-to-one-finding',
|
|
239
|
+
acceptedContracts: [{ schema: INFRASTRUCTURE_OBSERVATION_SCHEMA, versions: [1], mode: 'direct' }], emittedContract: { schema: EXTERNAL_FINDINGS_SCHEMA, version: 5 },
|
|
240
|
+
shapeIds: ['external-interchange.infrastructure.v1', 'external-interchange.findings.v5'], boundProfileIds: ['external-interchange.infrastructure.bounds', 'external-interchange.document.bounds'], hookIds: ['external-interchange.infrastructure.convert', 'external-interchange.findings.serialise'], serialisationProfileId: 'external-interchange.findings.json.v5', privacyProfileId: 'external-interchange.privacy.transient', retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'external-interchange.consumer.infrastructure-compare', plane: 'cli', operation: 'offline-infrastructure-comparison',
|
|
244
|
+
acceptedContracts: [{ schema: INFRASTRUCTURE_COMPARISON_INPUT_SCHEMA, versions: [1], mode: 'direct' }], emittedContract: null,
|
|
245
|
+
shapeIds: ['external-interchange.infrastructure-comparison.v1'], boundProfileIds: ['external-interchange.infrastructure-comparison.bounds'], hookIds: ['external-interchange.infrastructure.compare'], serialisationProfileId: null, privacyProfileId: 'external-interchange.privacy.transient', retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
id: 'external-interchange.consumer.findings-v4-read', plane: 'shared', operation: 'preserve-historical-findings',
|
|
249
|
+
acceptedContracts: [{ schema: EXTERNAL_FINDINGS_SCHEMA, versions: [4], mode: 'direct' }], emittedContract: null,
|
|
250
|
+
shapeIds: ['external-interchange.findings.v4'], boundProfileIds: ['external-interchange.document.bounds'], hookIds: ['external-interchange.findings.normalise'], serialisationProfileId: null, privacyProfileId: 'external-interchange.privacy.transient', retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
251
|
+
},
|
|
184
252
|
{
|
|
185
253
|
id: 'external-interchange.consumer.findings-normalise', plane: 'shared', operation: 'normalise-strict-findings',
|
|
186
|
-
acceptedContracts: [{ schema: EXTERNAL_FINDINGS_SCHEMA, versions: [
|
|
254
|
+
acceptedContracts: [{ schema: EXTERNAL_FINDINGS_SCHEMA, versions: [5], mode: 'direct' }],
|
|
187
255
|
emittedContract: { schema: EXTERNAL_FINDINGS_SCHEMA, version: EXTERNAL_FINDINGS_VERSION },
|
|
188
|
-
shapeIds: ['external-interchange.findings.
|
|
256
|
+
shapeIds: ['external-interchange.findings.v5'], boundProfileIds: ['external-interchange.document.bounds'],
|
|
189
257
|
hookIds: ['external-interchange.findings.normalise', 'external-interchange.findings.serialise'],
|
|
190
|
-
serialisationProfileId: 'external-interchange.findings.json.
|
|
258
|
+
serialisationProfileId: 'external-interchange.findings.json.v5', privacyProfileId: 'external-interchange.privacy.transient',
|
|
191
259
|
retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
192
260
|
},
|
|
193
261
|
{
|
|
194
262
|
id: 'external-interchange.consumer.finding-rows', plane: 'shared', operation: 'convert-finding-rows',
|
|
195
263
|
acceptedContracts: [{ schema: EXTERNAL_FINDING_ROWS_SCHEMA, versions: [1], mode: 'direct' }],
|
|
196
264
|
emittedContract: { schema: EXTERNAL_FINDINGS_SCHEMA, version: EXTERNAL_FINDINGS_VERSION },
|
|
197
|
-
shapeIds: ['external-interchange.finding-rows.v1', 'external-interchange.findings.
|
|
265
|
+
shapeIds: ['external-interchange.finding-rows.v1', 'external-interchange.findings.v5'], boundProfileIds: ['external-interchange.document.bounds'],
|
|
198
266
|
hookIds: ['external-interchange.finding-rows.convert', 'external-interchange.findings.serialise'],
|
|
199
|
-
serialisationProfileId: 'external-interchange.findings.json.
|
|
267
|
+
serialisationProfileId: 'external-interchange.findings.json.v5', privacyProfileId: 'external-interchange.privacy.transient',
|
|
200
268
|
retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
201
269
|
},
|
|
202
270
|
{
|
|
@@ -207,15 +275,15 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_LIFECYCLE_FAMILY = defineSchemaLif
|
|
|
207
275
|
{ schema: CERTIFICATE_OBSERVATION_ROWS_SCHEMA, versions: [1], mode: 'direct' },
|
|
208
276
|
],
|
|
209
277
|
emittedContract: { schema: EXTERNAL_FINDINGS_SCHEMA, version: EXTERNAL_FINDINGS_VERSION },
|
|
210
|
-
shapeIds: ['external-interchange.domain-rows.v1', 'external-interchange.dns-rows.v1', 'external-interchange.certificate-rows.v1', 'external-interchange.findings.
|
|
278
|
+
shapeIds: ['external-interchange.domain-rows.v1', 'external-interchange.dns-rows.v1', 'external-interchange.certificate-rows.v1', 'external-interchange.findings.v5'],
|
|
211
279
|
boundProfileIds: ['external-interchange.document.bounds'], hookIds: ['external-interchange.observation-rows.convert', 'external-interchange.findings.serialise'],
|
|
212
|
-
serialisationProfileId: 'external-interchange.findings.json.
|
|
280
|
+
serialisationProfileId: 'external-interchange.findings.json.v5', privacyProfileId: 'external-interchange.privacy.transient',
|
|
213
281
|
retentionEffect: 'transient_report', ...externalConsumerCommon,
|
|
214
282
|
},
|
|
215
283
|
{
|
|
216
284
|
id: 'external-interchange.consumer.case-merge', plane: 'shared', operation: 'non-destructive-case-merge',
|
|
217
|
-
acceptedContracts: [{ schema: EXTERNAL_FINDINGS_SCHEMA, versions: [
|
|
218
|
-
shapeIds: ['external-interchange.findings.v4'], boundProfileIds: ['external-interchange.document.bounds'],
|
|
285
|
+
acceptedContracts: [{ schema: EXTERNAL_FINDINGS_SCHEMA, versions: [...SUPPORTED_EXTERNAL_FINDINGS_VERSIONS], mode: 'direct' }], emittedContract: null,
|
|
286
|
+
shapeIds: ['external-interchange.findings.v4', 'external-interchange.findings.v5'], boundProfileIds: ['external-interchange.document.bounds'],
|
|
219
287
|
hookIds: ['external-interchange.findings.merge'], serialisationProfileId: null,
|
|
220
288
|
privacyProfileId: 'external-interchange.privacy.case-merge', retentionEffect: 'browser_indexeddb', ...externalConsumerCommon,
|
|
221
289
|
},
|
|
@@ -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 =
|
|
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: '
|
|
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
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const MESSAGE_INTAKE_SCHEMA = 'whoisleuth.message-intake';
|
|
2
|
-
export const MESSAGE_INTAKE_VERSION =
|
|
2
|
+
export const MESSAGE_INTAKE_VERSION = 2;
|
|
3
|
+
export const MESSAGE_INTAKE_LEGACY_VERSION = 1;
|
|
3
4
|
export const MESSAGE_INTAKE_KINDS = ['text', 'email', 'calendar', 'qr', 'pdf', 'docx', 'har', 'identity'];
|
|
4
5
|
export const MESSAGE_INTAKE_INPUTS = {
|
|
5
6
|
text: { label: 'Pasted text or links', accept: '.txt,text/plain', binary: false },
|
|
@@ -28,4 +29,9 @@ export const MAX_INTAKE_LINKS = 512;
|
|
|
28
29
|
export const MAX_INTAKE_URL_LENGTH = 8_192;
|
|
29
30
|
export const MAX_EMBEDDED_LINK_DEPTH = 8;
|
|
30
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'];
|
|
31
37
|
export const MESSAGE_ACTION_HINTS = ['clipboard_instruction', 'shell_instruction', 'verification_prompt', 'device_code_instruction', 'consent_instruction'];
|
|
@@ -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 =
|
|
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
|
|
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
|
|
298
|
+
version,
|
|
299
299
|
role: 'document',
|
|
300
|
-
lifecycle: 'current',
|
|
300
|
+
lifecycle: version === RISK_CALIBRATION_DATASET_VERSION ? 'current' : 'legacy',
|
|
301
301
|
readable: true,
|
|
302
|
-
emitted:
|
|
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: [
|
|
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:
|
|
340
|
-
role: '
|
|
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
|
-
...
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
658
|
+
acceptedContracts: [{ schema: RISK_CALIBRATION_DATASET_SCHEMA, versions: [...SUPPORTED_RISK_CALIBRATION_DATASET_VERSIONS], mode: 'direct', discriminator: null }],
|
|
645
659
|
emittedContract: null,
|
|
646
|
-
shapeIds:
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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: [
|
|
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
|
|
@@ -2,7 +2,7 @@ export { MAX_WEB_CAPTURE_MANIFEST_BYTES, WEB_CAPTURE_MANIFEST_SCHEMA, WEB_CAPTUR
|
|
|
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 =
|
|
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;
|