@slicedearth/whoisleuth-cli 2.2.0 → 2.4.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/NOTICE +6 -0
- package/README.md +20 -15
- package/bin/whoisleuth.mjs +8 -1
- package/cli/archive-content-digest.mjs +14 -0
- package/cli/archive-inspect.mjs +20 -53
- package/cli/arguments.mjs +454 -1748
- package/cli/artifact-validation/case-response.mjs +66 -35
- package/cli/artifact-validation/investigation-capsule.mjs +52 -31
- package/cli/artifact-validation/lookup-evidence.mjs +12 -6
- package/cli/artifact-validation/signed-review.mjs +112 -72
- package/cli/artifact-validation/structure-primitives.mjs +1 -105
- package/cli/artifact-verify.mjs +90 -24
- package/cli/assurance-command-runner.mjs +39 -4
- package/cli/bagit-folder.mjs +57 -0
- package/cli/bagit-review.mjs +23 -0
- package/cli/bounded-json.mjs +1 -1
- package/cli/bulk-checkpoint.mjs +34 -3
- package/cli/bulk-command-runner.mjs +2 -0
- package/cli/bulk-output.mjs +29 -3
- package/cli/case-command.mjs +195 -0
- package/cli/case-pack.mjs +66 -111
- package/cli/command-argument-grammar.mjs +215 -0
- package/cli/command-reference.mjs +342 -285
- package/cli/completion.mjs +303 -80
- package/cli/config-profile.mjs +7 -5
- package/cli/ct-event-intake.mjs +12 -12
- package/cli/discover.mjs +4 -3
- package/cli/discovery-observation-snapshot.mjs +59 -18
- package/cli/discovery-scan-command-runner.mjs +21 -0
- package/cli/discovery-scan.mjs +13 -4
- package/cli/discovery-workflow.mjs +1 -1
- package/cli/domain-control-monitor.mjs +50 -20
- package/cli/domain-control-observations.mjs +149 -102
- package/cli/errors.mjs +33 -1
- package/cli/evidence-command-runner.mjs +16 -5
- package/cli/evidence-signing.mjs +2 -2
- package/cli/external-observation-mapping.mjs +7 -8
- package/cli/formatters/terminal-lookup.mjs +18 -46
- package/cli/formatters/terminal-shared.mjs +5 -3
- package/cli/formatters/terminal-technology.mjs +114 -0
- package/cli/inline-command-families.mjs +2 -0
- package/cli/input.mjs +116 -0
- package/cli/interactive-launcher.mjs +2 -160
- package/cli/interchange-report.mjs +18 -8
- package/cli/investigation-artifacts.mjs +176 -0
- package/cli/investigation-checkpoint.mjs +10 -0
- package/cli/investigation-folder.mjs +114 -0
- package/cli/investigation-manifest.mjs +1 -112
- package/cli/investigation-package-review.mjs +103 -0
- package/cli/investigation-plan.mjs +32 -19
- package/cli/investigation-run.mjs +188 -33
- package/cli/local-document-checkpoint.mjs +170 -0
- package/cli/lookalike-calibration.mjs +7 -2
- package/cli/lookup-brief.mjs +4 -2
- package/cli/lookup-browser-view.mjs +1 -1
- package/cli/lookup-browser.mjs +5 -12
- package/cli/lookup-command-runner.mjs +17 -6
- package/cli/lookup-diff.mjs +37 -3
- package/cli/lookup-plan.mjs +11 -5
- package/cli/lookup-reconcile.mjs +10 -8
- package/cli/mail-header-review.mjs +467 -0
- package/cli/mail-review.mjs +66 -14
- package/cli/manual.mjs +1 -0
- package/cli/network-command-runner.mjs +2 -0
- package/cli/output-file.mjs +31 -5
- package/cli/registry-doctor.mjs +3 -1
- package/cli/registry-support.mjs +1 -1
- package/cli/retained-artifact-diff.mjs +2 -2
- package/cli/review-command-runner.mjs +70 -0
- package/cli/risk-calibration.mjs +19 -17
- package/cli/runner.mjs +62 -7
- package/cli/sharing-review.mjs +21 -34
- package/cli/signer-trust.mjs +104 -0
- package/cli/source-reliability.mjs +74 -83
- package/cli/terminal-input.mjs +168 -0
- package/cli/workflow-command-runner.mjs +68 -13
- package/docs/cli-reference.md +77 -24
- package/docs/cli.md +300 -25
- package/lib/abort.mjs +4 -1
- package/lib/availability.mjs +161 -112
- package/lib/bounded-file.mjs +3 -1
- package/lib/bounded-html-document.mjs +125 -0
- package/lib/bounded-json.mjs +51 -8
- package/lib/browser-library-profile.mjs +42 -51
- package/lib/browser-library-worker.mjs +112 -0
- package/lib/client-behavior-profile.mjs +3 -3
- package/lib/ct-search.mjs +11 -4
- package/lib/dns-convergence-review.mjs +1 -0
- package/lib/dns-delegation-health.mjs +24 -14
- package/lib/dns-inheritance-review.mjs +217 -0
- package/lib/dns-intelligence.mjs +73 -26
- package/lib/dns-mx.mjs +1 -1
- package/lib/dnssec-chain-validation.mjs +6 -0
- package/lib/dnssec-evidence-validation.mjs +11 -3
- package/lib/domain-change-packet.mjs +49 -16
- package/lib/domain-change-review.mjs +14 -8
- package/lib/domain-control-flight-recorder.mjs +221 -117
- package/lib/domain-control-manifest.mjs +129 -69
- package/lib/domain-posture-analysis.mjs +20 -7
- package/lib/domain-posture-parsers.mjs +201 -8
- package/lib/domain-posture.mjs +147 -29
- package/lib/evidence-export-privacy.mjs +561 -0
- package/lib/evidence-export.mjs +11 -543
- package/lib/evidence-report.mjs +5 -3
- package/lib/favicon.mjs +117 -41
- package/lib/generated/cisa-kev-catalog.mjs +12 -4
- package/lib/generated/registrar-standing-catalogue.mjs +7 -7
- package/lib/generated/retire-browser-catalog.mjs +2335 -940
- package/lib/hostname.mjs +2 -38
- package/lib/html-signals.mjs +111 -108
- package/lib/http-evidence-bounds.mjs +2 -1
- package/lib/http-intelligence.mjs +39 -26
- package/lib/local-geoip-evidence.mjs +19 -3
- package/lib/lookup-cache.mjs +34 -11
- package/lib/lookup-child-profile-contract.mjs +24 -15
- package/lib/lookup-diagnostics.mjs +24 -1
- package/lib/lookup-progress.mjs +30 -13
- package/lib/lookup-response-contract.mjs +1048 -0
- package/lib/lookup-response.mjs +8 -10
- package/lib/lookup-source-progress.mjs +40 -14
- package/lib/lookup.mjs +48 -27
- package/lib/nameserver-preflight-review.mjs +1 -0
- package/lib/observed-network-context.mjs +43 -27
- package/lib/outbound-request-bounds.mjs +4 -1
- package/lib/page-fingerprints.mjs +69 -133
- package/lib/page-role-profile.mjs +12 -8
- package/lib/perceptual-hash.mjs +43 -14
- package/lib/rdap-bootstrap.mjs +72 -22
- package/lib/rdap-capabilities.mjs +1 -1
- package/lib/rdap-client.mjs +15 -7
- package/lib/rdap-normalization.mjs +33 -18
- package/lib/rdap-search-workbench.mjs +1 -1
- package/lib/rdap-transport.mjs +47 -20
- package/lib/rdap-types.mjs +2 -1
- package/lib/rdap.mjs +18 -3
- package/lib/registrable-domain.mjs +21 -1
- package/lib/registrar-standing-contract.mjs +1 -0
- package/lib/registry-capabilities.mjs +5 -1
- package/lib/registry-capability-catalogue.mjs +2 -1
- package/lib/registry-dates.mjs +2 -190
- package/lib/registry-insights.mjs +85 -34
- package/lib/response-policy.mjs +86 -48
- package/lib/risk-calibration-summary.mjs +18 -6
- package/lib/rpki-evidence.mjs +8 -5
- package/lib/safe-fetch.mjs +54 -47
- package/lib/security-txt.mjs +42 -7
- package/lib/service-binding-dns.mjs +8 -0
- package/lib/smtp-transport-review.mjs +27 -15
- package/lib/sslbl-certificates.generated.mjs +136 -135
- package/lib/static-html-analysis.mjs +178 -151
- package/lib/structured-data-identity.mjs +1 -0
- package/lib/technology-markup.mjs +100 -0
- package/lib/threat-intelligence-manifests.mjs +11 -139
- package/lib/threat-intelligence-runtime.mjs +24 -52
- package/lib/threat-intelligence-targets.mjs +6 -34
- package/lib/threat-intelligence-types.mjs +39 -0
- package/lib/typosquat-generator.mjs +19 -15
- package/lib/urlhaus-intelligence.mjs +8 -3
- package/lib/urlscan-intelligence.mjs +1 -1
- package/lib/website-security-posture.mjs +30 -6
- package/lib/website-technology.mjs +153 -45
- package/lib/whois-authority.mjs +14 -2
- package/lib/whois-chain.mjs +9 -2
- package/lib/whois-common-formats.mjs +5 -5
- package/lib/whois-contracts.mjs +2 -1
- package/lib/whois-dialects.mjs +2 -2
- package/lib/whois-parser-support.mjs +8 -1
- package/lib/whois-transport.mjs +23 -7
- package/lib/zone-intent-review.mjs +16 -6
- package/package.json +2 -1
- package/packages/cases/case-attachment-model.mjs +83 -0
- package/packages/cases/case-evidence-model.mjs +156 -62
- package/packages/cases/case-export-input.mjs +53 -0
- package/packages/cases/case-migration-model.mjs +127 -44
- package/packages/cases/case-model.mjs +1 -0
- package/packages/cases/case-recheck-model.mjs +91 -0
- package/packages/cases/case-record-contracts.mjs +5 -20
- package/packages/cases/case-record-core.mjs +12 -22
- package/packages/cases/case-record-decisions.mjs +72 -0
- package/packages/cases/case-record-model.mjs +1 -0
- package/packages/cases/case-record-operations.mjs +95 -31
- package/packages/cases/case-record-projection.mjs +221 -0
- package/packages/cases/case-report.mjs +70 -54
- package/packages/cases/case-response-actions.mjs +654 -0
- package/packages/cases/case-response-model.mjs +64 -1115
- package/packages/cases/case-response-outcomes.mjs +317 -0
- package/packages/cases/case-response-packet-render.mjs +153 -0
- package/packages/cases/case-response-packet-types.mjs +1 -0
- package/packages/cases/case-response-packet-vocabulary.mjs +48 -0
- package/packages/cases/case-response-packet.mjs +74 -572
- package/packages/cases/case-response-records.mjs +94 -0
- package/packages/cases/case-response-review-inputs.mjs +371 -0
- package/packages/cases/case-response-values.mjs +85 -0
- package/packages/cases/case-review-package.mjs +45 -0
- package/packages/cases/case-selection.mjs +46 -0
- package/packages/cases/case-storage-model.mjs +31 -2
- package/packages/cases/response-route-freshness.mjs +16 -0
- package/packages/comparison/capture-context.mjs +61 -0
- package/packages/comparison/comparison-ledger-bulk.mjs +13 -11
- package/packages/comparison/page-similarity.mjs +5 -2
- package/packages/comparison/relationship-evidence.mjs +85 -8
- package/packages/comparison/relationship-provenance.mjs +93 -0
- package/packages/contracts/analyst-interchange.mjs +216 -0
- package/packages/contracts/analyst-review-state-contract.mjs +11 -0
- package/packages/contracts/analyst-review-state.mjs +5 -4
- package/packages/contracts/case-portability.mjs +366 -83
- package/packages/contracts/case-views-contract.mjs +12 -0
- package/packages/contracts/case-views.mjs +26 -0
- package/packages/contracts/cli-command-semantics.mjs +94 -0
- package/packages/contracts/cli-lookup.mjs +0 -1
- package/packages/contracts/domain-control-flight-recorder.mjs +80 -42
- package/packages/contracts/domain-control-manifest.mjs +127 -73
- package/packages/contracts/domain-control-monitor.mjs +48 -45
- package/packages/contracts/domain-control-review.mjs +179 -121
- package/packages/contracts/domain-name.mjs +21 -0
- package/packages/contracts/external-observation-interchange.mjs +2 -1
- package/packages/contracts/extracted-domain-lifecycle.mjs +11 -32
- package/packages/contracts/http-url.mjs +2 -0
- package/packages/contracts/investigation-package-limits.mjs +24 -0
- package/packages/contracts/investigation-portability.mjs +56 -27
- package/packages/contracts/investigation-run.mjs +16 -0
- package/packages/contracts/ip-address.mjs +34 -0
- package/packages/contracts/lookup-evidence.mjs +35 -0
- package/packages/contracts/offline-comparison.mjs +1 -2
- package/packages/contracts/page-fingerprints.mjs +15 -0
- package/packages/contracts/risk-calibration.mjs +15 -11
- package/packages/contracts/schema-compatibility.mjs +1 -1
- package/packages/contracts/schema-lifecycle.mjs +83 -153
- package/packages/contracts/selected-file-limits.mjs +6 -0
- package/packages/contracts/vulnerability-identifiers.mjs +5 -0
- package/packages/contracts/web-capture.mjs +10 -0
- package/packages/contracts/workspace-portability.mjs +183 -211
- package/packages/evidence/artifact-integrity.mjs +8 -2
- package/packages/evidence/artifact-structure.mjs +105 -0
- package/packages/evidence/decision-fact.mjs +4 -1
- package/packages/evidence/domain-control-runtime.mjs +201 -33
- package/packages/evidence/domain-posture-context.mjs +79 -0
- package/packages/evidence/image-regions.mjs +56 -0
- package/packages/evidence/latest-observations.mjs +28 -0
- package/packages/evidence/lookup-target.mjs +104 -0
- package/packages/evidence/observation.mjs +16 -1
- package/packages/evidence/passphrase-encryption.mjs +44 -0
- package/packages/evidence/record-identity.mjs +72 -0
- package/packages/evidence/registry-dates.mjs +190 -0
- package/packages/evidence/retained-file.mjs +69 -0
- package/packages/evidence/review-age.mjs +14 -0
- package/packages/interchange/bagit.mjs +342 -0
- package/packages/interchange/bounded-zip-extraction.mjs +278 -0
- package/packages/interchange/crc32.mjs +17 -0
- package/packages/interchange/external-findings-import.mjs +92 -51
- package/packages/interchange/web-capture-import.mjs +382 -0
- package/packages/investigation/bulk-mail-exposure.mjs +2 -1
- package/packages/investigation/investigation-bagit.mjs +14 -0
- package/packages/investigation/investigation-capsule.mjs +33 -5
- package/packages/investigation/investigation-manifest.mjs +200 -0
- package/packages/investigation/investigation-package-crypto.mjs +98 -0
- package/packages/investigation/investigation-package.mjs +200 -0
- package/packages/investigation/lookup-asset-graph-inputs.mjs +38 -0
- package/packages/investigation/lookup-asset-graph.mjs +193 -165
- package/packages/investigation/lookup-claim-readiness.mjs +18 -0
- package/packages/investigation/lookup-investigation-brief.mjs +3 -3
- package/packages/investigation/lookup-task-guidance.mjs +58 -0
- package/packages/monitoring/analyst-review-state.mjs +38 -90
- package/packages/workspace/brand-profile-model.mjs +276 -22
- package/packages/workspace/bulk-columns.mjs +17 -0
- package/packages/workspace/bulk-review-model.mjs +23 -11
- package/packages/workspace/bulk-session-model.mjs +100 -24
- package/packages/workspace/bulk-sort.mjs +1 -0
- package/packages/workspace/case-views.mjs +102 -0
- package/packages/workspace/detection-rule-model.mjs +70 -22
- package/packages/workspace/hostile-input.mjs +29 -8
- package/packages/workspace/investigation-template-model.mjs +19 -4
- package/packages/workspace/page-baseline.mjs +18 -15
- package/packages/workspace/relationship-observation-model.mjs +41 -23
- package/packages/workspace/watchlist-history.mjs +2 -2
- package/packages/workspace/watchlist-store.mjs +8 -2
- package/packages/workspace/website-snapshot-model.mjs +164 -26
- package/packages/workspace/workspace-archive-crypto.mjs +41 -61
- package/packages/workspace/workspace-archive.mjs +87 -21
- package/third-party-notices.txt +29 -2
- package/cli/evidence-command-arguments.mjs +0 -156
- package/packages/investigation/bulk-review-export.mjs +0 -63
|
@@ -8,6 +8,8 @@ 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;
|
|
10
10
|
export const MAX_EXTERNAL_FINDING_DOMAINS = 25;
|
|
11
|
+
export const MAX_EXTERNAL_FINDING_LIMITATIONS = 8;
|
|
12
|
+
export const MAX_EXTERNAL_FINDING_LIMITATION_LENGTH = 240;
|
|
11
13
|
export const EXTERNAL_FINDING_ROWS_SCHEMA = 'whoisleuth.external-finding-rows';
|
|
12
14
|
export const EXTERNAL_FINDING_ROWS_VERSION = 1;
|
|
13
15
|
export const DOMAIN_OBSERVATION_ROWS_SCHEMA = 'whoisleuth.domain-observation-rows';
|
|
@@ -147,7 +149,6 @@ export const EXTERNAL_OBSERVATION_INTERCHANGE_LIFECYCLE_FAMILY = defineSchemaLif
|
|
|
147
149
|
contracts: EXTERNAL_INTERCHANGE_CONTRACTS,
|
|
148
150
|
fixtures: EXTERNAL_INTERCHANGE_FIXTURES,
|
|
149
151
|
metadata: {
|
|
150
|
-
metadataVersion: 3,
|
|
151
152
|
enforcement: 'declarative_only',
|
|
152
153
|
shapes: [
|
|
153
154
|
externalShape('external-interchange.findings.v4', EXTERNAL_FINDINGS_SCHEMA, [...SUPPORTED_EXTERNAL_FINDINGS_VERSIONS], ['schema', 'schemaVersion', 'source', 'findings'], 'preserve_document'),
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
function formatSlug(id) {
|
|
2
2
|
return id.replaceAll('.', '-');
|
|
3
3
|
}
|
|
4
|
-
function lifecycleShapeId(format, version
|
|
5
|
-
return
|
|
6
|
-
? `${formatSlug(format.descriptor.id)}.v${version}`
|
|
7
|
-
: `${formatSlug(format.descriptor.id)}.document`;
|
|
4
|
+
function lifecycleShapeId(format, version) {
|
|
5
|
+
return `${formatSlug(format.descriptor.id)}.v${version}`;
|
|
8
6
|
}
|
|
9
7
|
function contractState(format, version) {
|
|
10
8
|
const current = version === format.descriptor.currentVersion;
|
|
@@ -21,7 +19,7 @@ function contractState(format, version) {
|
|
|
21
19
|
: null,
|
|
22
20
|
};
|
|
23
21
|
}
|
|
24
|
-
function fixtureRecord(format, fixture
|
|
22
|
+
function fixtureRecord(format, fixture) {
|
|
25
23
|
const state = contractState(format, fixture.version);
|
|
26
24
|
const output = format.fixtures.find((candidate) => candidate.version === format.descriptor.currentVersion);
|
|
27
25
|
return {
|
|
@@ -38,12 +36,11 @@ function fixtureRecord(format, fixture, v4) {
|
|
|
38
36
|
? output?.id ?? null
|
|
39
37
|
: null,
|
|
40
38
|
scope: 'repository',
|
|
41
|
-
|
|
39
|
+
shapeId: lifecycleShapeId(format, fixture.version),
|
|
42
40
|
};
|
|
43
41
|
}
|
|
44
|
-
function buildExtractedLifecycleFamily(options
|
|
45
|
-
const
|
|
46
|
-
const fixtures = options.formats.flatMap((format) => format.fixtures.map((fixture) => (fixtureRecord(format, fixture, v4))));
|
|
42
|
+
export function buildExtractedLifecycleFamily(options) {
|
|
43
|
+
const fixtures = options.formats.flatMap((format) => format.fixtures.map((fixture) => (fixtureRecord(format, fixture))));
|
|
47
44
|
const contracts = options.formats.flatMap((format) => format.descriptor.supportedVersions.map((version) => ({
|
|
48
45
|
compatibilityId: format.descriptor.id,
|
|
49
46
|
schema: format.lifecycleSchema,
|
|
@@ -58,23 +55,19 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
58
55
|
.filter((fixture) => fixture.schema === format.lifecycleSchema && fixture.version === version)
|
|
59
56
|
.map((fixture) => fixture.id),
|
|
60
57
|
})));
|
|
61
|
-
const shapes = options.formats.flatMap((format) => (
|
|
62
|
-
|
|
63
|
-
: [format.descriptor.currentVersion]).map((version) => ({
|
|
64
|
-
id: lifecycleShapeId(format, version, v4),
|
|
58
|
+
const shapes = options.formats.flatMap((format) => format.descriptor.supportedVersions.map((version) => ({
|
|
59
|
+
id: lifecycleShapeId(format, version),
|
|
65
60
|
schema: format.lifecycleSchema,
|
|
66
|
-
versions:
|
|
61
|
+
versions: [version],
|
|
67
62
|
objects: [{
|
|
68
63
|
path: '$',
|
|
69
64
|
requiredKeys: format.requiredKeys,
|
|
70
65
|
optionalKeys: format.optionalKeys,
|
|
71
|
-
...(v4 ? { alternativeRequiredKeys: [] } : {}),
|
|
72
66
|
unknownKeys: 'reject',
|
|
73
67
|
}],
|
|
74
68
|
fixedArrays: [],
|
|
75
69
|
normalisation: 'preserve_document',
|
|
76
70
|
target: null,
|
|
77
|
-
...(v4 ? { discriminator: null } : {}),
|
|
78
71
|
})));
|
|
79
72
|
const boundProfiles = options.formats.map((format) => ({
|
|
80
73
|
id: `${formatSlug(format.descriptor.id)}.bounds`,
|
|
@@ -120,9 +113,7 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
120
113
|
const outputOnly = format.descriptor.futureVersionBehavior === 'not_applicable';
|
|
121
114
|
const acceptedVersions = outputOnly ? [] : format.descriptor.supportedVersions;
|
|
122
115
|
const edgeVersions = outputOnly ? [format.descriptor.currentVersion] : format.descriptor.supportedVersions;
|
|
123
|
-
const shapeIds =
|
|
124
|
-
? edgeVersions.map((version) => lifecycleShapeId(format, version, true))
|
|
125
|
-
: [lifecycleShapeId(format, format.descriptor.currentVersion, false)];
|
|
116
|
+
const shapeIds = edgeVersions.map((version) => lifecycleShapeId(format, version));
|
|
126
117
|
const hookId = hookIdFor(format);
|
|
127
118
|
const serialises = index === 0;
|
|
128
119
|
return {
|
|
@@ -134,13 +125,11 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
134
125
|
schema: format.lifecycleSchema,
|
|
135
126
|
versions: acceptedVersions,
|
|
136
127
|
mode: 'direct',
|
|
137
|
-
...(metadataVersion >= 3 ? { discriminator: null } : {}),
|
|
138
128
|
}]
|
|
139
129
|
: [],
|
|
140
130
|
emittedContract: {
|
|
141
131
|
schema: format.lifecycleSchema,
|
|
142
132
|
version: format.descriptor.currentVersion,
|
|
143
|
-
...(v4 ? { discriminator: null } : {}),
|
|
144
133
|
},
|
|
145
134
|
shapeIds,
|
|
146
135
|
boundProfileIds: [`${formatSlug(format.descriptor.id)}.bounds`],
|
|
@@ -155,7 +144,6 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
155
144
|
};
|
|
156
145
|
});
|
|
157
146
|
const metadata = {
|
|
158
|
-
metadataVersion,
|
|
159
147
|
enforcement: 'declarative_only',
|
|
160
148
|
shapes,
|
|
161
149
|
boundProfiles,
|
|
@@ -181,7 +169,7 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
181
169
|
projection: options.projection,
|
|
182
170
|
includedCategories: options.includedCategories,
|
|
183
171
|
excludedCategories: options.excludedCategories,
|
|
184
|
-
notePolicy: 'discarded',
|
|
172
|
+
notePolicy: options.notePolicy ?? 'discarded',
|
|
185
173
|
retention: options.retention,
|
|
186
174
|
network: 'none',
|
|
187
175
|
sharingReview: options.retention === 'operator_controlled_output' ? 'required' : 'not_applicable',
|
|
@@ -207,12 +195,3 @@ function buildExtractedLifecycleFamily(options, metadataVersion) {
|
|
|
207
195
|
metadata,
|
|
208
196
|
};
|
|
209
197
|
}
|
|
210
|
-
export function buildExtractedLifecycleFamilyV2(options) {
|
|
211
|
-
return buildExtractedLifecycleFamily(options, 2);
|
|
212
|
-
}
|
|
213
|
-
export function buildExtractedLifecycleFamilyV3(options) {
|
|
214
|
-
return buildExtractedLifecycleFamily(options, 3);
|
|
215
|
-
}
|
|
216
|
-
export function buildExtractedLifecycleFamilyV4(options) {
|
|
217
|
-
return buildExtractedLifecycleFamily(options, 4);
|
|
218
|
-
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MAX_SELECTED_FILES, MAX_SELECTED_FILE_TOTAL_BYTES, MAX_SELECTED_FILE_BYTES } from "./selected-file-limits.mjs";
|
|
2
|
+
import { MAX_EDITABLE_CASE_OUTPUT_BYTES } from "./case-portability.mjs";
|
|
3
|
+
// A complete Case handoff carries every admitted original plus the Case JSON.
|
|
4
|
+
// File-retention bounds remain independent of this container allowance.
|
|
5
|
+
export const MAX_INVESTIGATION_MANIFEST_ARTIFACTS = MAX_SELECTED_FILES + 1;
|
|
6
|
+
export const MAX_INVESTIGATION_MANIFEST_ARTIFACT_BYTES = MAX_SELECTED_FILE_BYTES;
|
|
7
|
+
export const MAX_INVESTIGATION_MANIFEST_TOTAL_BYTES = MAX_SELECTED_FILE_TOTAL_BYTES + MAX_EDITABLE_CASE_OUTPUT_BYTES;
|
|
8
|
+
export const MAX_INVESTIGATION_MANIFEST_DOCUMENT_BYTES = 512 * 1024;
|
|
9
|
+
export const MAX_INVESTIGATION_PACKAGE_ENTRIES = MAX_INVESTIGATION_MANIFEST_ARTIFACTS + 1;
|
|
10
|
+
// Stored ZIP entries use 76 header bytes and two generated ASCII paths (at
|
|
11
|
+
// most 21 bytes each). 128 bytes per entry plus the 22-byte end record cover
|
|
12
|
+
// this writer's overhead without reducing the independently admitted payload.
|
|
13
|
+
export const MAX_INVESTIGATION_PACKAGE_BYTES = MAX_INVESTIGATION_MANIFEST_TOTAL_BYTES
|
|
14
|
+
+ MAX_INVESTIGATION_MANIFEST_DOCUMENT_BYTES + MAX_INVESTIGATION_PACKAGE_ENTRIES * 128 + 22;
|
|
15
|
+
export const ENCRYPTED_INVESTIGATION_PACKAGE_MAGIC = 'WHOISLEUTH-ENCRYPTED\0';
|
|
16
|
+
export const ENCRYPTED_INVESTIGATION_PACKAGE_VERSION = 1;
|
|
17
|
+
// Magic, version byte, iteration count, salt, IV and plaintext byte count.
|
|
18
|
+
export const ENCRYPTED_INVESTIGATION_PACKAGE_HEADER_BYTES = ENCRYPTED_INVESTIGATION_PACKAGE_MAGIC.length + 1 + 4 + 16 + 12 + 4;
|
|
19
|
+
export const MAX_ENCRYPTED_INVESTIGATION_PACKAGE_BYTES = MAX_INVESTIGATION_PACKAGE_BYTES
|
|
20
|
+
+ ENCRYPTED_INVESTIGATION_PACKAGE_HEADER_BYTES + 16;
|
|
21
|
+
export function hasEncryptedInvestigationPackagePrefix(bytes) {
|
|
22
|
+
return bytes.byteLength >= ENCRYPTED_INVESTIGATION_PACKAGE_MAGIC.length
|
|
23
|
+
&& [...ENCRYPTED_INVESTIGATION_PACKAGE_MAGIC].every((character, index) => bytes[index] === character.charCodeAt(0));
|
|
24
|
+
}
|
|
@@ -22,27 +22,44 @@ export const BULK_MAIL_EXPOSURE_EXPORT_VERSION = 2;
|
|
|
22
22
|
export const SUPPORTED_BULK_MAIL_EXPOSURE_EXPORT_VERSIONS = Object.freeze([BULK_MAIL_EXPOSURE_EXPORT_VERSION]);
|
|
23
23
|
export const MAX_BULK_MAIL_EXPOSURE_ROWS = 2_000;
|
|
24
24
|
export const BULK_REVIEW_MANIFEST_SCHEMA = 'whoisleuth.bulk-review-manifest';
|
|
25
|
-
export const BULK_REVIEW_MANIFEST_VERSION =
|
|
26
|
-
export const SUPPORTED_BULK_REVIEW_MANIFEST_VERSIONS = Object.freeze([BULK_REVIEW_MANIFEST_VERSION]);
|
|
25
|
+
export const BULK_REVIEW_MANIFEST_VERSION = 3;
|
|
26
|
+
export const SUPPORTED_BULK_REVIEW_MANIFEST_VERSIONS = Object.freeze([2, BULK_REVIEW_MANIFEST_VERSION]);
|
|
27
27
|
export const INVESTIGATION_CAPSULE_SCHEMA = 'whoisleuth.investigation-capsule';
|
|
28
|
-
export const INVESTIGATION_CAPSULE_VERSION =
|
|
28
|
+
export const INVESTIGATION_CAPSULE_VERSION = 4;
|
|
29
29
|
export const PUBLIC_INVESTIGATION_CAPSULE_VERSION = 2;
|
|
30
30
|
export const SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS = Object.freeze([
|
|
31
31
|
PUBLIC_INVESTIGATION_CAPSULE_VERSION,
|
|
32
|
+
3,
|
|
32
33
|
INVESTIGATION_CAPSULE_VERSION,
|
|
33
34
|
]);
|
|
34
35
|
export const INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA = 'whoisleuth.case-analyst-records';
|
|
35
36
|
export const INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION = 1;
|
|
36
37
|
export const LOOKUP_INVESTIGATION_BRIEF_SCHEMA = 'whoisleuth.investigation-brief';
|
|
37
|
-
export const LOOKUP_INVESTIGATION_BRIEF_VERSION =
|
|
38
|
+
export const LOOKUP_INVESTIGATION_BRIEF_VERSION = 3;
|
|
38
39
|
export const PUBLIC_LOOKUP_INVESTIGATION_BRIEF_VERSION = 1;
|
|
39
40
|
export const SUPPORTED_LOOKUP_INVESTIGATION_BRIEF_VERSIONS = Object.freeze([
|
|
40
41
|
PUBLIC_LOOKUP_INVESTIGATION_BRIEF_VERSION,
|
|
42
|
+
2,
|
|
41
43
|
LOOKUP_INVESTIGATION_BRIEF_VERSION,
|
|
42
44
|
]);
|
|
43
45
|
export const MAX_LOOKUP_INVESTIGATION_BRIEF_BYTES = 128 * 1024;
|
|
44
46
|
export const LOOKUP_ASSET_GRAPH_SCHEMA = 'whoisleuth.lookup-asset-graph';
|
|
45
|
-
export const LOOKUP_ASSET_GRAPH_VERSION =
|
|
47
|
+
export const LOOKUP_ASSET_GRAPH_VERSION = 3;
|
|
48
|
+
export const SUPPORTED_LOOKUP_ASSET_GRAPH_VERSIONS = Object.freeze([2, LOOKUP_ASSET_GRAPH_VERSION]);
|
|
49
|
+
// Offline-parser emergency bounds exceed every relationship that the bounded
|
|
50
|
+
// graph inputs can produce. The writer does not truncate nodes or edges.
|
|
51
|
+
export const MAX_LOOKUP_ASSET_NODES = 8_192;
|
|
52
|
+
export const MAX_LOOKUP_ASSET_EDGES = 8_192;
|
|
53
|
+
export const MAX_LOOKUP_ASSET_LIMITATIONS = 16;
|
|
54
|
+
export const MAX_LOOKUP_ASSET_INPUT_ROWS = 160;
|
|
55
|
+
export function investigationCapsuleContracts(version) {
|
|
56
|
+
switch (version) {
|
|
57
|
+
case 2: return { brief: 1, graph: 2 };
|
|
58
|
+
case 3: return { brief: 2, graph: 2 };
|
|
59
|
+
case INVESTIGATION_CAPSULE_VERSION: return { brief: LOOKUP_INVESTIGATION_BRIEF_VERSION, graph: LOOKUP_ASSET_GRAPH_VERSION };
|
|
60
|
+
default: return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
46
63
|
export const INVESTIGATION_DOMAIN_COMPATIBILITY_FACADES = Object.freeze([
|
|
47
64
|
['frontend/src/lib/analysis/acquisition-decision-packet.ts', 'packages/investigation/acquisition-decision-packet.mts'],
|
|
48
65
|
['frontend/src/lib/analysis/acquisition-due-diligence.ts', 'packages/investigation/acquisition-due-diligence.mts'],
|
|
@@ -89,20 +106,20 @@ export const BULK_REVIEW_MANIFEST_COMPATIBILITY = defineSchemaCompatibility({
|
|
|
89
106
|
currentVersion: BULK_REVIEW_MANIFEST_VERSION, supportedVersions: SUPPORTED_BULK_REVIEW_MANIFEST_VERSIONS,
|
|
90
107
|
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'read_only', writeSemantics: 'read_only',
|
|
91
108
|
byteBudget: MAX_INVESTIGATION_PORTABLE_BYTES, owner: INVESTIGATION_PORTABILITY_CONTRACT_OWNER,
|
|
92
|
-
note: 'Version
|
|
109
|
+
note: 'Version 3 retains nullable batch, row and source observation times in one selected Bulk review with deterministic sorted-json-v2 integrity. Published version 2 remains readable without inventing absent source times. Raw payloads, contacts, notes and transient request state are excluded.',
|
|
93
110
|
});
|
|
94
111
|
export const INVESTIGATION_CAPSULE_COMPATIBILITY = defineSchemaCompatibility({
|
|
95
112
|
id: 'export.investigation-capsule', kind: 'export', schema: INVESTIGATION_CAPSULE_SCHEMA,
|
|
96
113
|
currentVersion: INVESTIGATION_CAPSULE_VERSION, supportedVersions: SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS,
|
|
97
114
|
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'read_only', writeSemantics: 'read_only',
|
|
98
115
|
byteBudget: MAX_INVESTIGATION_PORTABLE_BYTES, owner: INVESTIGATION_PORTABILITY_CONTRACT_OWNER,
|
|
99
|
-
note: 'Version
|
|
116
|
+
note: 'Version 4 embeds brief v3 and graph v3 with projection coverage. Versions 2 and 3 remain readable with their exact embedded contracts and whole-capsule sorted-json-v2 integrity.',
|
|
100
117
|
});
|
|
101
118
|
export const LOOKUP_ASSET_GRAPH_COMPATIBILITY = defineSchemaCompatibility({
|
|
102
119
|
id: 'derived.lookup-asset-graph', kind: 'derived', schema: LOOKUP_ASSET_GRAPH_SCHEMA,
|
|
103
120
|
tier: 'durable_interchange',
|
|
104
|
-
currentVersion: LOOKUP_ASSET_GRAPH_VERSION, supportedVersions:
|
|
105
|
-
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: '
|
|
121
|
+
currentVersion: LOOKUP_ASSET_GRAPH_VERSION, supportedVersions: SUPPORTED_LOOKUP_ASSET_GRAPH_VERSIONS,
|
|
122
|
+
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'read_only', writeSemantics: 'read_only',
|
|
106
123
|
byteBudget: null, owner: INVESTIGATION_PORTABILITY_CONTRACT_OWNER,
|
|
107
124
|
note: 'Bounded relationship projection embedded in investigation capsules; source attribution and incomplete evidence remain explicit.',
|
|
108
125
|
});
|
|
@@ -120,7 +137,7 @@ export const LOOKUP_INVESTIGATION_BRIEF_COMPATIBILITY = defineSchemaCompatibilit
|
|
|
120
137
|
currentVersion: LOOKUP_INVESTIGATION_BRIEF_VERSION, supportedVersions: SUPPORTED_LOOKUP_INVESTIGATION_BRIEF_VERSIONS,
|
|
121
138
|
acceptsUnversionedLegacy: false, futureVersionBehavior: 'reject', migration: 'read_only', writeSemantics: 'none',
|
|
122
139
|
byteBudget: MAX_LOOKUP_INVESTIGATION_BRIEF_BYTES, owner: INVESTIGATION_PORTABILITY_CONTRACT_OWNER,
|
|
123
|
-
note: 'Version
|
|
140
|
+
note: 'Version 3 summarises the complete retained graph with canonical Decision Facts. Versions 1 and 2 retain their exact historical relationship bounds within supported capsules.',
|
|
124
141
|
});
|
|
125
142
|
export const INVESTIGATION_PORTABILITY_COMPATIBILITY = Object.freeze([
|
|
126
143
|
ACQUISITION_DECISION_PACKET_COMPATIBILITY,
|
|
@@ -134,17 +151,24 @@ export const INVESTIGATION_PORTABILITY_COMPATIBILITY = Object.freeze([
|
|
|
134
151
|
LOOKUP_INVESTIGATION_BRIEF_COMPATIBILITY,
|
|
135
152
|
]);
|
|
136
153
|
const INVESTIGATION_FIXTURES = Object.freeze([
|
|
154
|
+
{ id: 'investigation-capsule-v4', path: 'test/fixtures/investigation-portability/investigation-capsule-v4.json', bytes: 9005, sha256: 'a1c193ab16fe79cbd39182b4a554e09ce785f71c19aa8185f442a3cc06d54830', schema: INVESTIGATION_CAPSULE_SCHEMA, version: 4, role: 'current' },
|
|
155
|
+
{ id: 'lookup-asset-graph-v3', path: 'test/fixtures/investigation-portability/lookup-asset-graph-v3.json', bytes: 8821, sha256: 'b37ce0d3cc18af95e09dc0e34b6a610a7e0fcbb9ab095b5da6a0d72c54d63c30', schema: LOOKUP_ASSET_GRAPH_SCHEMA, version: 3, role: 'current' },
|
|
156
|
+
{ id: 'lookup-investigation-brief-v3', path: 'test/fixtures/investigation-portability/lookup-investigation-brief-v3.json', bytes: 1779, sha256: '49b78aa7b7c620ac521c329a30af990b33114e4122028e277e1419b352944e8b', schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, version: 3, role: 'current' },
|
|
137
157
|
{ id: 'acquisition-decision-v2', path: 'test/fixtures/investigation-portability/acquisition-decision-v2.json', bytes: 6_278, sha256: '1c1b5c2fcea2886dae5661085f605d95317b89bb6d9774cb8967a754ef8165bf', schema: ACQUISITION_DECISION_PACKET_SCHEMA, version: 2, role: 'current' },
|
|
138
158
|
{ id: 'lookup-claim-passport-v1', path: 'test/fixtures/investigation-portability/lookup-claim-passport-v1.json', bytes: 2_011, sha256: 'dbf1c3975282e340b6639162a0555aeaed42c06abe92ed3b354409ce73c284a4', schema: LOOKUP_CLAIM_PASSPORT_SCHEMA, version: 1, role: 'current' },
|
|
139
159
|
{ id: 'bulk-domain-comparison-v4', path: 'test/fixtures/investigation-portability/bulk-domain-comparison-v4.json', bytes: 17_079, sha256: 'b718af34c8f5f1ba4427807cd149561bc1b7e605a6e74206a694beaee078cc2d', schema: BULK_DOMAIN_COMPARISON_SCHEMA, version: 4, role: 'current' },
|
|
140
160
|
{ id: 'bulk-mail-exposure-v2', path: 'test/fixtures/investigation-portability/bulk-mail-exposure-v2.json', bytes: 2_582, sha256: '9ff6c4c9f2dda4c5451daf8fb11e36a3ee15b513a09ad3c93515cc37df5d6660', schema: BULK_MAIL_EXPOSURE_SCHEMA, version: 2, role: 'current' },
|
|
141
|
-
{ id: 'bulk-review-manifest-v2', path: 'test/fixtures/investigation-portability/bulk-review-manifest-v2.json', bytes:
|
|
161
|
+
{ id: 'bulk-review-manifest-v2', path: 'test/fixtures/investigation-portability/bulk-review-manifest-v2-current.json', bytes: 2_118, sha256: 'b4e209df9bc0e1c8be8a34d4f4aac486df9d0a4e1a1f750b9a21ab6e0d35b7b6', schema: BULK_REVIEW_MANIFEST_SCHEMA, version: 2, role: 'historical' },
|
|
162
|
+
{ id: 'bulk-review-manifest-v3', path: 'test/fixtures/investigation-portability/bulk-review-manifest-v3.json', bytes: 2_422, sha256: '0ee1022140b8d19a92100806f0091c197be0ffec0faae808721c47d7cb96d9ad', schema: BULK_REVIEW_MANIFEST_SCHEMA, version: 3, role: 'current' },
|
|
163
|
+
// Synthetic integrity examples deliberately combine independently versioned
|
|
164
|
+
// contracts. Their application labels are not captured-release provenance;
|
|
165
|
+
// historical/current here describes the supported capsule schema only.
|
|
142
166
|
{ id: 'investigation-capsule-v2', path: 'test/fixtures/investigation-capsule-v2.json', bytes: 3_286, sha256: 'fb71cb243020d401e3653bb714f9de07a71b81622fcf83c0027599b763dda070', schema: INVESTIGATION_CAPSULE_SCHEMA, version: 2, role: 'historical' },
|
|
143
|
-
{ id: 'investigation-capsule-v3', path: 'test/fixtures/investigation-portability/investigation-capsule-v3.json', bytes: 6_132, sha256: '685123c8bd152ee1a8074441bcd56bbde9fb0304aa4a320ee9b37d02061ed82a', schema: INVESTIGATION_CAPSULE_SCHEMA, version: 3, role: '
|
|
144
|
-
{ id: 'lookup-asset-graph-v2', path: 'test/fixtures/investigation-portability/lookup-asset-graph-v2.json', bytes: 1_157, sha256: '455397a2b2987180d54657199e76c4dc175e01aed0fa83d945a6f3ec30bdcd49', schema: LOOKUP_ASSET_GRAPH_SCHEMA, version: 2, role: '
|
|
167
|
+
{ id: 'investigation-capsule-v3', path: 'test/fixtures/investigation-portability/investigation-capsule-v3.json', bytes: 6_132, sha256: '685123c8bd152ee1a8074441bcd56bbde9fb0304aa4a320ee9b37d02061ed82a', schema: INVESTIGATION_CAPSULE_SCHEMA, version: 3, role: 'historical' },
|
|
168
|
+
{ id: 'lookup-asset-graph-v2', path: 'test/fixtures/investigation-portability/lookup-asset-graph-v2.json', bytes: 1_157, sha256: '455397a2b2987180d54657199e76c4dc175e01aed0fa83d945a6f3ec30bdcd49', schema: LOOKUP_ASSET_GRAPH_SCHEMA, version: 2, role: 'historical' },
|
|
145
169
|
{ id: 'investigation-analyst-records-v1', path: 'test/fixtures/investigation-portability/investigation-analyst-records-v1.json', bytes: 624, sha256: '0730116afef29e52b448e150f6755e89ec1189c2fbc6ec4ef8cfc4b41f677456', schema: INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA, version: 1, role: 'current' },
|
|
146
170
|
{ id: 'lookup-investigation-brief-v1', path: 'test/fixtures/investigation-portability/lookup-investigation-brief-v1.json', bytes: 1_651, sha256: 'bc21c886671370659149c3e494c7e6061302569308823c69ef96f0c601dadbab', schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, version: 1, role: 'historical' },
|
|
147
|
-
{ id: 'lookup-investigation-brief-v2', path: 'test/fixtures/investigation-portability/lookup-investigation-brief-v2.json', bytes: 1_724, sha256: '25d0133318df8daa00848e6a2c03913478beb30818a4959298ec1500b6aaa0fd', schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, version: 2, role: '
|
|
171
|
+
{ id: 'lookup-investigation-brief-v2', path: 'test/fixtures/investigation-portability/lookup-investigation-brief-v2.json', bytes: 1_724, sha256: '25d0133318df8daa00848e6a2c03913478beb30818a4959298ec1500b6aaa0fd', schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, version: 2, role: 'historical' },
|
|
148
172
|
].map((fixture) => Object.freeze({
|
|
149
173
|
...fixture,
|
|
150
174
|
contentDigestSha256: null,
|
|
@@ -182,7 +206,7 @@ const INVESTIGATION_CONTRACTS = Object.freeze([
|
|
|
182
206
|
...SUPPORTED_BULK_MAIL_EXPOSURE_EXPORT_VERSIONS.map((version) => investigationContract({ compatibilityId: BULK_MAIL_EXPOSURE_COMPATIBILITY.id, schema: BULK_MAIL_EXPOSURE_SCHEMA, version, currentVersion: BULK_MAIL_EXPOSURE_EXPORT_VERSION, canonicalisation: 'sorted-json-v2', byteBudget: MAX_INVESTIGATION_PORTABLE_BYTES })),
|
|
183
207
|
...SUPPORTED_BULK_REVIEW_MANIFEST_VERSIONS.map((version) => investigationContract({ compatibilityId: BULK_REVIEW_MANIFEST_COMPATIBILITY.id, schema: BULK_REVIEW_MANIFEST_SCHEMA, version, currentVersion: BULK_REVIEW_MANIFEST_VERSION, canonicalisation: 'sorted-json-v2', byteBudget: MAX_INVESTIGATION_PORTABLE_BYTES })),
|
|
184
208
|
...SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS.map((version) => investigationContract({ compatibilityId: INVESTIGATION_CAPSULE_COMPATIBILITY.id, schema: INVESTIGATION_CAPSULE_SCHEMA, version, currentVersion: INVESTIGATION_CAPSULE_VERSION, canonicalisation: 'sorted-json-v2', byteBudget: MAX_INVESTIGATION_PORTABLE_BYTES })),
|
|
185
|
-
investigationContract({ compatibilityId: LOOKUP_ASSET_GRAPH_COMPATIBILITY.id, schema: LOOKUP_ASSET_GRAPH_SCHEMA, version
|
|
209
|
+
...SUPPORTED_LOOKUP_ASSET_GRAPH_VERSIONS.map((version) => investigationContract({ compatibilityId: LOOKUP_ASSET_GRAPH_COMPATIBILITY.id, schema: LOOKUP_ASSET_GRAPH_SCHEMA, version, currentVersion: LOOKUP_ASSET_GRAPH_VERSION, canonicalisation: null, byteBudget: null })),
|
|
186
210
|
investigationContract({ compatibilityId: INVESTIGATION_CAPSULE_ANALYST_RECORDS_COMPATIBILITY.id, schema: INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA, version: INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION, currentVersion: INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION, canonicalisation: null, byteBudget: null }),
|
|
187
211
|
...SUPPORTED_LOOKUP_INVESTIGATION_BRIEF_VERSIONS.map((version) => investigationContract({ compatibilityId: LOOKUP_INVESTIGATION_BRIEF_COMPATIBILITY.id, schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, version, currentVersion: LOOKUP_INVESTIGATION_BRIEF_VERSION, canonicalisation: null, byteBudget: MAX_LOOKUP_INVESTIGATION_BRIEF_BYTES })),
|
|
188
212
|
]);
|
|
@@ -203,11 +227,12 @@ const INVESTIGATION_SHAPES = Object.freeze([
|
|
|
203
227
|
investigationShape('investigation.domain-comparison.v4', BULK_DOMAIN_COMPARISON_SCHEMA, [...SUPPORTED_BULK_DOMAIN_COMPARISON_EXPORT_VERSIONS], ['schema', 'version', 'generatedAt', 'comparison', 'integrity'], 'preserve_signed_document'),
|
|
204
228
|
investigationShape('investigation.mail-exposure.v2', BULK_MAIL_EXPOSURE_SCHEMA, [...SUPPORTED_BULK_MAIL_EXPOSURE_EXPORT_VERSIONS], ['schema', 'version', 'report', 'integrity'], 'preserve_signed_document'),
|
|
205
229
|
investigationShape('investigation.bulk-review.v2', BULK_REVIEW_MANIFEST_SCHEMA, [...SUPPORTED_BULK_REVIEW_MANIFEST_VERSIONS], ['schema', 'version', 'generatedAt', 'observedAt', 'lookupProfile', 'selection', 'view', 'rows', 'limitations', 'integrity'], 'preserve_signed_document'),
|
|
206
|
-
investigationShape('investigation.capsule.v2-
|
|
207
|
-
investigationShape('investigation.asset-graph.v2', LOOKUP_ASSET_GRAPH_SCHEMA, [
|
|
230
|
+
investigationShape('investigation.capsule.v2-v4', INVESTIGATION_CAPSULE_SCHEMA, [...SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS], ['schema', 'schemaVersion', 'generatedAt', 'application', 'target', 'sourceContracts', 'investigationBrief', 'graphSnapshot', 'analystRecords', 'limitations', 'integrity'], 'preserve_signed_document'),
|
|
231
|
+
investigationShape('investigation.asset-graph.v2', LOOKUP_ASSET_GRAPH_SCHEMA, [2], ['version', 'targetId', 'nodes', 'edges', 'sources', 'truncated', 'limitations'], 'preserve_document'),
|
|
232
|
+
investigationShape('investigation.asset-graph.v3', LOOKUP_ASSET_GRAPH_SCHEMA, [LOOKUP_ASSET_GRAPH_VERSION], ['version', 'targetId', 'nodes', 'edges', 'sources', 'coverage', 'truncated', 'limitations'], 'preserve_document'),
|
|
208
233
|
investigationShape('investigation.analyst-records.v1', INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA, [INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION], ['caseId', 'status', 'disposition', 'decisions', 'assertions'], 'preserve_document'),
|
|
209
234
|
investigationShape('investigation.brief.v1', LOOKUP_INVESTIGATION_BRIEF_SCHEMA, [PUBLIC_LOOKUP_INVESTIGATION_BRIEF_VERSION], ['schema', 'schemaVersion', 'generatedAt', 'target', 'targetType', 'task', 'taskLabel', 'question', 'summary', 'observation', 'verifiedFacts', 'contradictions', 'unknowns', 'nextActions', 'relationships', 'limitations'], 'preserve_document'),
|
|
210
|
-
investigationShape('investigation.brief.v2', LOOKUP_INVESTIGATION_BRIEF_SCHEMA, [LOOKUP_INVESTIGATION_BRIEF_VERSION], ['schema', 'schemaVersion', 'generatedAt', 'target', 'targetType', 'task', 'taskLabel', 'question', 'summary', 'observation', 'decisionFacts', 'relationships', 'limitations'], 'preserve_document'),
|
|
235
|
+
investigationShape('investigation.brief.v2-v3', LOOKUP_INVESTIGATION_BRIEF_SCHEMA, [2, LOOKUP_INVESTIGATION_BRIEF_VERSION], ['schema', 'schemaVersion', 'generatedAt', 'target', 'targetType', 'task', 'taskLabel', 'question', 'summary', 'observation', 'decisionFacts', 'relationships', 'limitations'], 'preserve_document'),
|
|
211
236
|
]);
|
|
212
237
|
const investigationConsumerCommon = Object.freeze({
|
|
213
238
|
expiryPolicyId: 'investigation.expiry.not-applicable',
|
|
@@ -223,7 +248,6 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
223
248
|
contracts: INVESTIGATION_CONTRACTS,
|
|
224
249
|
fixtures: INVESTIGATION_FIXTURES,
|
|
225
250
|
metadata: {
|
|
226
|
-
metadataVersion: 3,
|
|
227
251
|
enforcement: 'declarative_only',
|
|
228
252
|
shapes: INVESTIGATION_SHAPES,
|
|
229
253
|
boundProfiles: [
|
|
@@ -242,6 +266,11 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
242
266
|
{ id: 'investigation.derived.bounds', bounds: [
|
|
243
267
|
{ id: 'projection-items', path: '$', phase: 'normalised', unit: 'items', minimum: 0, maximum: 2_000, handling: 'truncate' },
|
|
244
268
|
] },
|
|
269
|
+
{ id: 'investigation.graph.bounds', bounds: [
|
|
270
|
+
{ id: 'nodes', path: 'nodes', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_LOOKUP_ASSET_NODES, handling: 'reject' },
|
|
271
|
+
{ id: 'edges', path: 'edges', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_LOOKUP_ASSET_EDGES, handling: 'reject' },
|
|
272
|
+
{ id: 'input-coverage', path: 'coverage.inputs', phase: 'normalised', unit: 'items', minimum: 0, maximum: MAX_LOOKUP_ASSET_INPUT_ROWS, handling: 'reject' },
|
|
273
|
+
] },
|
|
245
274
|
],
|
|
246
275
|
hooks: [
|
|
247
276
|
{ id: 'investigation.offline.structure', role: 'structure_validator', runtime: 'cli', module: 'cli/offline-artifact-validation.mts', exportName: 'validateOfflineArtifactStructure' },
|
|
@@ -258,7 +287,7 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
258
287
|
{ id: 'investigation.brief.build', role: 'builder', runtime: 'shared', module: 'packages/investigation/lookup-investigation-brief.mts', exportName: 'buildLookupInvestigationBrief' },
|
|
259
288
|
],
|
|
260
289
|
serialisationProfiles: [{
|
|
261
|
-
id: 'investigation.capsule.json.v2-
|
|
290
|
+
id: 'investigation.capsule.json.v2-v4',
|
|
262
291
|
schema: INVESTIGATION_CAPSULE_SCHEMA,
|
|
263
292
|
versions: [...SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS],
|
|
264
293
|
mediaType: 'application/json',
|
|
@@ -289,7 +318,7 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
289
318
|
{ schema: INVESTIGATION_CAPSULE_SCHEMA, versions: [...SUPPORTED_INVESTIGATION_CAPSULE_VERSIONS], mode: 'direct' },
|
|
290
319
|
],
|
|
291
320
|
emittedContract: null,
|
|
292
|
-
shapeIds: ['investigation.acquisition.v2', 'investigation.claim-passport.v1', 'investigation.domain-comparison.v4', 'investigation.mail-exposure.v2', 'investigation.bulk-review.v2', 'investigation.capsule.v2-
|
|
321
|
+
shapeIds: ['investigation.acquisition.v2', 'investigation.claim-passport.v1', 'investigation.domain-comparison.v4', 'investigation.mail-exposure.v2', 'investigation.bulk-review.v2', 'investigation.capsule.v2-v4'],
|
|
293
322
|
boundProfileIds: ['investigation.portable.bounds', 'investigation.passport.bounds'],
|
|
294
323
|
hookIds: ['investigation.offline.structure', 'investigation.offline.verify'],
|
|
295
324
|
serialisationProfileId: null,
|
|
@@ -298,15 +327,15 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
298
327
|
{
|
|
299
328
|
id: 'investigation.consumer.capsule-compose', plane: 'shared', operation: 'compose-and-verify-capsule',
|
|
300
329
|
acceptedContracts: [
|
|
301
|
-
{ schema: LOOKUP_ASSET_GRAPH_SCHEMA, versions: [
|
|
330
|
+
{ schema: LOOKUP_ASSET_GRAPH_SCHEMA, versions: [...SUPPORTED_LOOKUP_ASSET_GRAPH_VERSIONS], mode: 'embedded' },
|
|
302
331
|
{ schema: INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA, versions: [INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION], mode: 'embedded' },
|
|
303
332
|
{ schema: LOOKUP_INVESTIGATION_BRIEF_SCHEMA, versions: [...SUPPORTED_LOOKUP_INVESTIGATION_BRIEF_VERSIONS], mode: 'embedded' },
|
|
304
333
|
],
|
|
305
334
|
emittedContract: { schema: INVESTIGATION_CAPSULE_SCHEMA, version: INVESTIGATION_CAPSULE_VERSION },
|
|
306
|
-
shapeIds: ['investigation.asset-graph.v2', 'investigation.analyst-records.v1', 'investigation.brief.v1', 'investigation.brief.v2', 'investigation.capsule.v2-
|
|
307
|
-
boundProfileIds: ['investigation.portable.bounds', 'investigation.brief.bounds', 'investigation.derived.bounds'],
|
|
335
|
+
shapeIds: ['investigation.asset-graph.v2', 'investigation.asset-graph.v3', 'investigation.analyst-records.v1', 'investigation.brief.v1', 'investigation.brief.v2-v3', 'investigation.capsule.v2-v4'],
|
|
336
|
+
boundProfileIds: ['investigation.portable.bounds', 'investigation.brief.bounds', 'investigation.derived.bounds', 'investigation.graph.bounds'],
|
|
308
337
|
hookIds: ['investigation.capsule.build', 'investigation.capsule.verify', 'investigation.capsule.serialise'],
|
|
309
|
-
serialisationProfileId: 'investigation.capsule.json.v2-
|
|
338
|
+
serialisationProfileId: 'investigation.capsule.json.v2-v4',
|
|
310
339
|
privacyProfileId: 'investigation.privacy.output', retentionEffect: 'operator_controlled_output', ...investigationConsumerCommon,
|
|
311
340
|
},
|
|
312
341
|
...[
|
|
@@ -315,9 +344,9 @@ export const INVESTIGATION_PORTABILITY_LIFECYCLE_FAMILY = defineSchemaLifecycleF
|
|
|
315
344
|
['investigation.consumer.domain-comparison-build', BULK_DOMAIN_COMPARISON_SCHEMA, BULK_DOMAIN_COMPARISON_EXPORT_VERSION, 'investigation.domain-comparison.v4', 'investigation.domain-comparison.build', 'investigation.portable.bounds'],
|
|
316
345
|
['investigation.consumer.mail-exposure-build', BULK_MAIL_EXPOSURE_SCHEMA, BULK_MAIL_EXPOSURE_EXPORT_VERSION, 'investigation.mail-exposure.v2', 'investigation.mail-exposure.build', 'investigation.portable.bounds'],
|
|
317
346
|
['investigation.consumer.bulk-review-build', BULK_REVIEW_MANIFEST_SCHEMA, BULK_REVIEW_MANIFEST_VERSION, 'investigation.bulk-review.v2', 'investigation.bulk-review.build', 'investigation.portable.bounds'],
|
|
318
|
-
['investigation.consumer.graph-build', LOOKUP_ASSET_GRAPH_SCHEMA, LOOKUP_ASSET_GRAPH_VERSION, 'investigation.asset-graph.
|
|
347
|
+
['investigation.consumer.graph-build', LOOKUP_ASSET_GRAPH_SCHEMA, LOOKUP_ASSET_GRAPH_VERSION, 'investigation.asset-graph.v3', 'investigation.graph.build', 'investigation.graph.bounds'],
|
|
319
348
|
['investigation.consumer.analyst-records-project', INVESTIGATION_CAPSULE_ANALYST_RECORDS_SCHEMA, INVESTIGATION_CAPSULE_ANALYST_RECORDS_VERSION, 'investigation.analyst-records.v1', 'investigation.capsule.build', 'investigation.derived.bounds'],
|
|
320
|
-
['investigation.consumer.brief-build', LOOKUP_INVESTIGATION_BRIEF_SCHEMA, LOOKUP_INVESTIGATION_BRIEF_VERSION, 'investigation.brief.v2', 'investigation.brief.build', 'investigation.brief.bounds'],
|
|
349
|
+
['investigation.consumer.brief-build', LOOKUP_INVESTIGATION_BRIEF_SCHEMA, LOOKUP_INVESTIGATION_BRIEF_VERSION, 'investigation.brief.v2-v3', 'investigation.brief.build', 'investigation.brief.bounds'],
|
|
321
350
|
].map(([id, schema, version, shapeId, hookId, boundProfileId]) => ({
|
|
322
351
|
id, plane: 'shared', operation: 'build-current-projection', acceptedContracts: [],
|
|
323
352
|
emittedContract: { schema, version }, shapeIds: [shapeId], boundProfileIds: [boundProfileId],
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const CLI_INVESTIGATION_RUN_SCHEMA = 'whoisleuth.cli.investigation-run';
|
|
2
|
+
export const CLI_INVESTIGATION_RUN_VERSION = 3;
|
|
3
|
+
export const SUPPORTED_CLI_INVESTIGATION_RUN_VERSIONS = Object.freeze([1, 2, 3]);
|
|
4
|
+
export const MAX_INVESTIGATION_RUN_BYTES = 24 * 1024 * 1024;
|
|
5
|
+
export const MAX_INVESTIGATION_RUN_SELECTIONS = 16;
|
|
6
|
+
export const MAX_INVESTIGATION_RUN_SELECTION_LENGTH = 1_024;
|
|
7
|
+
// Version 3 retains partial observations and content-bound step inputs. Earlier
|
|
8
|
+
// readers must reject these checkpoints rather than recollect or reinterpret them.
|
|
9
|
+
export const INVESTIGATION_RUN_STATES = Object.freeze([
|
|
10
|
+
'complete',
|
|
11
|
+
'partial',
|
|
12
|
+
'awaiting_network_approval',
|
|
13
|
+
'awaiting_analyst_selection',
|
|
14
|
+
'awaiting_review_confirmation',
|
|
15
|
+
'step_failed',
|
|
16
|
+
]);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function ipv6Groups(value) {
|
|
2
|
+
const address = addressValue(value);
|
|
3
|
+
if (address?.family !== 6)
|
|
4
|
+
return [];
|
|
5
|
+
return Array.from({ length: 8 }, (_, index) => ((address.value >> BigInt((7 - index) * 16)) & 0xffffn).toString(16).padStart(4, '0'));
|
|
6
|
+
}
|
|
7
|
+
export function addressValue(value) {
|
|
8
|
+
if (typeof value !== 'string' || value.length > 96)
|
|
9
|
+
return null;
|
|
10
|
+
if (/^\d{1,3}(?:\.\d{1,3}){3}$/u.test(value)) {
|
|
11
|
+
const octets = value.split('.').map(Number);
|
|
12
|
+
return octets.every(octet => octet >= 0 && octet <= 255)
|
|
13
|
+
? { family: 4, value: octets.reduce((total, octet) => (total << 8) + octet, 0) >>> 0 } : null;
|
|
14
|
+
}
|
|
15
|
+
if (!value.includes(':') || !/^[0-9a-f:.]+$/iu.test(value))
|
|
16
|
+
return null;
|
|
17
|
+
try {
|
|
18
|
+
const hostname = new URL(`https://[${value}]/`).hostname;
|
|
19
|
+
if (!hostname.startsWith('[') || !hostname.endsWith(']'))
|
|
20
|
+
return null;
|
|
21
|
+
const pieces = hostname.slice(1, -1).split('::');
|
|
22
|
+
const left = pieces[0] ? pieces[0].split(':') : [];
|
|
23
|
+
const right = pieces[1] ? pieces[1].split(':') : [];
|
|
24
|
+
const missing = 8 - left.length - right.length;
|
|
25
|
+
if (pieces.length > 2 || pieces.length === 1 && missing !== 0 || pieces.length === 2 && missing < 1
|
|
26
|
+
|| [...left, ...right].some(part => !/^[0-9a-f]{1,4}$/iu.test(part)))
|
|
27
|
+
return null;
|
|
28
|
+
const parts = [...left, ...Array.from({ length: missing }, () => '0'), ...right];
|
|
29
|
+
return { family: 6, value: parts.reduce((total, part) => (total << 16n) + BigInt(`0x${part}`), 0n) };
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineSchemaCompatibility } from "./schema-compatibility.mjs";
|
|
2
|
+
export const LOOKUP_EVIDENCE_SCHEMA = 'whoisleuth.lookup-evidence';
|
|
3
|
+
export const V1_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION = 26;
|
|
4
|
+
export const PUBLISHED_V2_LOOKUP_EVIDENCE_SCHEMA_VERSION = 27;
|
|
5
|
+
export const REGISTRAR_STANDING_LOOKUP_EVIDENCE_SCHEMA_VERSION = 28;
|
|
6
|
+
export const LATEST_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION = REGISTRAR_STANDING_LOOKUP_EVIDENCE_SCHEMA_VERSION;
|
|
7
|
+
export const HOSTNAME_SCOPED_LOOKUP_EVIDENCE_SCHEMA_VERSION = 29;
|
|
8
|
+
export const PRIVACY_MINIMIZED_LOOKUP_EVIDENCE_SCHEMA_VERSION = PUBLISHED_V2_LOOKUP_EVIDENCE_SCHEMA_VERSION;
|
|
9
|
+
export const LOOKUP_EVIDENCE_SCHEMA_VERSION = HOSTNAME_SCOPED_LOOKUP_EVIDENCE_SCHEMA_VERSION;
|
|
10
|
+
export const SUPPORTED_LOOKUP_EVIDENCE_SCHEMA_VERSIONS = Object.freeze([
|
|
11
|
+
V1_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION,
|
|
12
|
+
PUBLISHED_V2_LOOKUP_EVIDENCE_SCHEMA_VERSION,
|
|
13
|
+
LATEST_PUBLIC_LOOKUP_EVIDENCE_SCHEMA_VERSION,
|
|
14
|
+
LOOKUP_EVIDENCE_SCHEMA_VERSION,
|
|
15
|
+
]);
|
|
16
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_BYTES = 5 * 1024 * 1024;
|
|
17
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_ENTRIES = 20_000;
|
|
18
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_DEPTH = 24;
|
|
19
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_ARRAY_ITEMS = 10_000;
|
|
20
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_KEY_LENGTH = 256;
|
|
21
|
+
export const LOOKUP_EVIDENCE_PORTABLE_MAX_STRING_LENGTH = 1024 * 1024;
|
|
22
|
+
export const LOOKUP_EVIDENCE_COMPATIBILITY = defineSchemaCompatibility({
|
|
23
|
+
id: 'export.lookup-evidence',
|
|
24
|
+
kind: 'export',
|
|
25
|
+
schema: LOOKUP_EVIDENCE_SCHEMA,
|
|
26
|
+
currentVersion: LOOKUP_EVIDENCE_SCHEMA_VERSION,
|
|
27
|
+
supportedVersions: SUPPORTED_LOOKUP_EVIDENCE_SCHEMA_VERSIONS,
|
|
28
|
+
acceptsUnversionedLegacy: false,
|
|
29
|
+
futureVersionBehavior: 'reject',
|
|
30
|
+
migration: 'read_only',
|
|
31
|
+
writeSemantics: 'read_only',
|
|
32
|
+
byteBudget: LOOKUP_EVIDENCE_PORTABLE_MAX_BYTES,
|
|
33
|
+
owner: 'packages/contracts/lookup-evidence.mts',
|
|
34
|
+
note: 'Exact published versions 26, 27 and 28 remain replayable with their original collection scope. Version 29 identifies the hostname used for supporting DNS, TLS and web observations; registration authority remains separate.',
|
|
35
|
+
});
|
|
@@ -10,7 +10,7 @@ export const CLI_COMPARISON_LEDGER_SCHEMA = 'whoisleuth.cli.comparison-ledger';
|
|
|
10
10
|
export const CLI_COMPARISON_LEDGER_VERSION = 1;
|
|
11
11
|
export const MAX_RETAINED_ARTIFACT_DIFF_BYTES = 8 * 1024 * 1024;
|
|
12
12
|
export const RELATIONSHIP_EVIDENCE_SCHEMA = 'whoisleuth.relationship-evidence';
|
|
13
|
-
export const RELATIONSHIP_EVIDENCE_VERSION =
|
|
13
|
+
export const RELATIONSHIP_EVIDENCE_VERSION = 3;
|
|
14
14
|
export const TLS_RELATIONSHIP_PROFILE_VERSION = 2;
|
|
15
15
|
export const SUPPORTED_TLS_RELATIONSHIP_PROFILE_VERSIONS = Object.freeze([TLS_RELATIONSHIP_PROFILE_VERSION]);
|
|
16
16
|
export const OFFLINE_COMPARISON_COMPATIBILITY_FACADES = Object.freeze([
|
|
@@ -114,7 +114,6 @@ export const OFFLINE_COMPARISON_LIFECYCLE_FAMILY = defineSchemaLifecycleFamily({
|
|
|
114
114
|
contracts: OFFLINE_COMPARISON_CONTRACTS,
|
|
115
115
|
fixtures: OFFLINE_COMPARISON_FIXTURES,
|
|
116
116
|
metadata: {
|
|
117
|
-
metadataVersion: 4,
|
|
118
117
|
enforcement: 'declarative_only',
|
|
119
118
|
shapes: [
|
|
120
119
|
offlineOutputShape('offline-comparison.page-output.current', CLI_PAGE_COMPARE_SCHEMA, [4], ['schema', 'version', 'generatedAt', 'left', 'right', 'page', 'technology', 'tls', 'limitations']),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const PAGE_FINGERPRINT_VERSION = 2;
|
|
2
|
+
export const PAGE_FINGERPRINT_PARSERS = Object.freeze({
|
|
3
|
+
1: 'static-tag-sequence-v1',
|
|
4
|
+
[PAGE_FINGERPRINT_VERSION]: 'html-tree-v2',
|
|
5
|
+
});
|
|
6
|
+
export const MAX_STATIC_HTML_TAGS = 8_192;
|
|
7
|
+
export const MAX_STATIC_HTML_NODES = MAX_STATIC_HTML_TAGS * 3;
|
|
8
|
+
export const MAX_STATIC_HTML_DEPTH = 512;
|
|
9
|
+
// Each admitted element emits a start and end event; other nodes emit at most
|
|
10
|
+
// one event. The parser admits three mandatory document elements additionally.
|
|
11
|
+
export const MAX_STATIC_HTML_TREE_EVENTS = MAX_STATIC_HTML_NODES + MAX_STATIC_HTML_TAGS + 3;
|
|
12
|
+
export const PAGE_FINGERPRINT_TOKEN_LIMITS = Object.freeze({
|
|
13
|
+
1: 4_096,
|
|
14
|
+
[PAGE_FINGERPRINT_VERSION]: MAX_STATIC_HTML_TREE_EVENTS,
|
|
15
|
+
});
|
|
@@ -158,6 +158,15 @@ export const RISK_CALIBRATION_REPORT_PRIVACY_KEYS = Object.freeze([
|
|
|
158
158
|
export const RISK_CALIBRATION_REPORT_INTERPRETATION_KEYS = Object.freeze([
|
|
159
159
|
'authority', 'statement', 'automaticTuning', 'networkRequests', 'persisted',
|
|
160
160
|
]);
|
|
161
|
+
/** Stable disposition identities admitted by the versioned calibration schema. */
|
|
162
|
+
export const RISK_CALIBRATION_DISPOSITIONS = Object.freeze([
|
|
163
|
+
'unreviewed',
|
|
164
|
+
'suspicious',
|
|
165
|
+
'confirmed_abuse',
|
|
166
|
+
'false_positive',
|
|
167
|
+
'expected',
|
|
168
|
+
'closed_no_action',
|
|
169
|
+
]);
|
|
161
170
|
export const RISK_CALIBRATION_DATASET_COMPATIBILITY = defineSchemaCompatibility({
|
|
162
171
|
id: 'cli.risk-calibration-dataset',
|
|
163
172
|
kind: 'cli_document',
|
|
@@ -337,8 +346,8 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
|
|
|
337
346
|
{
|
|
338
347
|
id: 'risk-calibration-report-v3-detailed',
|
|
339
348
|
path: 'test/fixtures/risk-calibration-report-v3-detailed.json',
|
|
340
|
-
bytes:
|
|
341
|
-
sha256: '
|
|
349
|
+
bytes: 7_020,
|
|
350
|
+
sha256: 'a5cba1681c170c79f8891037f47efc93e0ae6ce5d247418ff3f1c9a81a352922',
|
|
342
351
|
contentDigestSha256: null,
|
|
343
352
|
schema: RISK_CALIBRATION_REPORT_SCHEMA,
|
|
344
353
|
version: RISK_CALIBRATION_REPORT_VERSION,
|
|
@@ -351,8 +360,8 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
|
|
|
351
360
|
{
|
|
352
361
|
id: 'risk-calibration-report-v3-summary',
|
|
353
362
|
path: 'test/fixtures/risk-calibration-report-v3-summary.json',
|
|
354
|
-
bytes:
|
|
355
|
-
sha256: '
|
|
363
|
+
bytes: 5_480,
|
|
364
|
+
sha256: '71b7fe1ee613b2ab32bd1f5646ee765985022c904224e1a08f4577c1d1d06240',
|
|
356
365
|
contentDigestSha256: null,
|
|
357
366
|
schema: RISK_CALIBRATION_REPORT_SCHEMA,
|
|
358
367
|
version: RISK_CALIBRATION_REPORT_VERSION,
|
|
@@ -364,7 +373,6 @@ export const RISK_CALIBRATION_SCHEMA_LIFECYCLE = defineSchemaLifecycleFamily({
|
|
|
364
373
|
},
|
|
365
374
|
],
|
|
366
375
|
metadata: {
|
|
367
|
-
metadataVersion: 4,
|
|
368
376
|
enforcement: 'declarative_only',
|
|
369
377
|
shapes: [
|
|
370
378
|
...[RISK_CALIBRATION_DATASET_VERSION].map((version) => ({
|
|
@@ -1110,9 +1118,7 @@ const FACTOR_SPEC = objectOf([
|
|
|
1110
1118
|
const REPORT_RECORD_SPEC = objectOf([
|
|
1111
1119
|
{ key: 'id', value: boundedText(MAX_RISK_CALIBRATION_RECORD_ID_LENGTH) },
|
|
1112
1120
|
{ key: 'domain', value: boundedText(MAX_RISK_CALIBRATION_DOMAIN_LENGTH) },
|
|
1113
|
-
{ key: 'analystDisposition', value: boundedText(MAX_RISK_CALIBRATION_DISPOSITION_LENGTH,
|
|
1114
|
-
'unreviewed', 'suspicious', 'confirmed_abuse', 'false_positive', 'expected', 'closed_no_action',
|
|
1115
|
-
]) },
|
|
1121
|
+
{ key: 'analystDisposition', value: boundedText(MAX_RISK_CALIBRATION_DISPOSITION_LENGTH, RISK_CALIBRATION_DISPOSITIONS) },
|
|
1116
1122
|
{ key: 'reviewReasonCode', value: nullable(boundedText(MAX_RISK_CALIBRATION_REVIEW_REASON_LENGTH)) },
|
|
1117
1123
|
{ key: 'interoperabilityTags', value: arrayOf(boundedText(MAX_RISK_CALIBRATION_STRING_LENGTH), 0, 32) },
|
|
1118
1124
|
{ key: 'metricClass', value: boundedText(16, ['positive', 'negative', 'excluded']) },
|
|
@@ -1179,9 +1185,7 @@ const DATASET_EVIDENCE_SPEC = objectOf([
|
|
|
1179
1185
|
const DATASET_RECORD_SPEC = objectOf([
|
|
1180
1186
|
{ key: 'id', value: boundedText(MAX_RISK_CALIBRATION_RECORD_ID_LENGTH, null, 1, canonicalRiskCalibrationIdentifier) },
|
|
1181
1187
|
{ key: 'domain', value: boundedText(MAX_RISK_CALIBRATION_DOMAIN_LENGTH, null, 1, validRiskCalibrationDomain) },
|
|
1182
|
-
{ key: 'analystDisposition', value: boundedText(MAX_RISK_CALIBRATION_DISPOSITION_LENGTH,
|
|
1183
|
-
'unreviewed', 'suspicious', 'confirmed_abuse', 'false_positive', 'expected', 'closed_no_action',
|
|
1184
|
-
]) },
|
|
1188
|
+
{ key: 'analystDisposition', value: boundedText(MAX_RISK_CALIBRATION_DISPOSITION_LENGTH, RISK_CALIBRATION_DISPOSITIONS) },
|
|
1185
1189
|
{ key: 'reviewReasonCode', value: boundedText(MAX_RISK_CALIBRATION_REVIEW_REASON_LENGTH, RISK_CALIBRATION_REVIEW_REASON_VALUES), optional: true },
|
|
1186
1190
|
{ key: 'evidence', value: DATASET_EVIDENCE_SPEC },
|
|
1187
1191
|
]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const LOCAL_SCHEMA_IDENTIFIER_SOURCE = String.raw `whoisleuth\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*`;
|
|
2
2
|
const LOCAL_SCHEMA_IDENTIFIER_PATTERN = new RegExp(`^${LOCAL_SCHEMA_IDENTIFIER_SOURCE}$`, 'u');
|
|
3
3
|
const COMPATIBILITY_SCHEMA_IDENTIFIER_PATTERN = /^[-a-z0-9.]+$/u;
|
|
4
|
-
const CONTRACT_KINDS = new Set(['browser_store', 'tab_store', 'hosted_store', 'export', 'cli_document', 'derived']);
|
|
4
|
+
const CONTRACT_KINDS = new Set(['browser_store', 'tab_store', 'hosted_store', 'filesystem_store', 'export', 'cli_document', 'derived']);
|
|
5
5
|
const COMPATIBILITY_TIERS = new Set(['durable_interchange', 'published_output', 'internal']);
|
|
6
6
|
const FUTURE_VERSION_BEHAVIORS = new Set(['reject', 'preserve_without_write', 'discard', 'not_applicable']);
|
|
7
7
|
const MIGRATION_BEHAVIORS = new Set(['normalize_to_current', 'exact_current_only', 'read_only', 'none']);
|