@slicedearth/whoisleuth-cli 1.47.4 → 2.0.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/README.md +74 -177
- package/SECURITY.md +6 -3
- package/bin/whoisleuth.mjs +2 -1
- package/cli/archive-inspect.mjs +28 -10
- package/cli/arguments.mjs +204 -174
- package/cli/artifact-structure.mjs +837 -163
- package/cli/artifact-verify.mjs +90 -61
- package/cli/bounded-json.mjs +1 -1
- package/cli/bulk-checkpoint.mjs +33 -20
- package/cli/bulk.mjs +9 -2
- package/cli/case-pack.mjs +180 -576
- package/cli/ci-report.mjs +6 -1
- package/cli/collection-preflight.mjs +2 -2
- package/cli/command-catalogue.mjs +12 -3
- package/cli/command-reference.mjs +910 -92
- package/cli/completion.mjs +504 -226
- package/cli/config-profile.mjs +13 -3
- package/cli/discover.mjs +7 -1
- package/cli/discovery-observation-snapshot.mjs +24 -28
- package/cli/discovery-scan-command-runner.mjs +9 -9
- package/cli/discovery-scan.mjs +17 -3
- package/cli/discovery-snapshot.mjs +15 -7
- package/cli/domain-control-monitor.mjs +203 -30
- package/cli/domain-control-observations.mjs +15 -21
- package/cli/errors.mjs +8 -3
- package/cli/evidence-signing.mjs +10 -20
- package/cli/external-observation-mapping.mjs +3 -3
- package/cli/formatters/json.mjs +20 -32
- package/cli/formatters/terminal.mjs +583 -22
- package/cli/input.mjs +7 -2
- package/cli/interactive-launcher.mjs +226 -0
- package/cli/interchange-report.mjs +19 -19
- package/cli/investigation-manifest.mjs +1 -1
- package/cli/investigation-plan.mjs +167 -16
- package/cli/investigation-run.mjs +9 -1
- package/cli/lookalike-calibration.mjs +3 -1
- package/cli/lookup-brief.mjs +13 -8
- package/cli/lookup-browser.mjs +844 -0
- package/cli/lookup-command-runner.mjs +94 -31
- package/cli/lookup-diff.mjs +2 -2
- package/cli/lookup-plan.mjs +1 -0
- package/cli/mail-review.mjs +206 -94
- package/cli/manual.mjs +5 -5
- package/cli/offline-evidence-review.mjs +18 -7
- package/cli/open-asset-model-bridge.mjs +1 -1
- package/cli/output-file.mjs +70 -14
- package/cli/page-compare.mjs +11 -6
- package/cli/progress-events.mjs +2 -1
- package/cli/progress.mjs +3 -3
- package/cli/registry-cohort.mjs +9 -51
- package/cli/registry-doctor.mjs +67 -28
- package/cli/retained-artifact-diff.mjs +7 -8
- package/cli/risk-calibration.mjs +85 -38
- package/cli/runner.mjs +189 -75
- package/cli/saved-lookup.mjs +424 -57
- package/cli/sharing-review.mjs +6 -1
- package/cli/source-reliability.mjs +75 -36
- package/cli/terminal-presentation.mjs +43 -18
- package/docs/cli-reference.md +125 -1708
- package/docs/cli.md +86 -254
- package/frontend/src/lib/analysis/domain-control-manifest-core.js +3 -145
- package/frontend/src/lib/analysis/domain-control-records.js +3 -88
- package/lib/availability.mjs +58 -40
- package/lib/bounded-contract-normalizers.mjs +2 -4
- package/lib/bounded-file.mjs +78 -4
- package/lib/bounded-json.mjs +51 -13
- package/lib/browser-library-profile.mjs +1 -1
- package/lib/classify.mjs +56 -5
- package/lib/client-behavior-profile.mjs +1 -1
- package/lib/credential-surface-profile.mjs +1 -1
- package/lib/cryptographic-assurance.mjs +35 -17
- package/lib/ct-query.mjs +3 -3
- package/lib/ct-search.mjs +37 -21
- package/lib/distributed-operation-budget.mjs +4 -2
- package/lib/dns-delegation-health.mjs +9 -6
- package/lib/dns-intelligence.mjs +1 -1
- package/lib/dnssec-chain-validation.mjs +2 -3
- package/lib/dnssec-evidence-validation.mjs +13 -7
- package/lib/domain-assurance.mjs +12 -12
- package/lib/domain-change-packet.mjs +1 -1
- package/lib/domain-control-flight-recorder.mjs +442 -78
- package/lib/domain-control-manifest.mjs +314 -59
- package/lib/domain-posture-analysis.mjs +5 -2
- package/lib/encrypted-dns-contract.mjs +2 -3
- package/lib/evidence-export.mjs +518 -36
- package/lib/external-intelligence-risk.mjs +26 -10
- package/lib/feature-policy.mjs +1 -1
- package/lib/homepage-metadata-contract.mjs +290 -0
- package/lib/hostname.mjs +1 -1
- package/lib/html-signals.mjs +89 -5
- package/lib/http-intelligence.mjs +331 -2
- package/lib/interchange-fidelity-registry.mjs +28 -26
- package/lib/lookup-cache.mjs +6 -4
- package/lib/lookup.mjs +25 -2
- package/lib/observed-network-context.mjs +1 -1
- package/lib/page-fingerprints.mjs +2 -2
- package/lib/page-role-profile.mjs +1 -1
- package/lib/portable-generator.mjs +8 -0
- package/lib/provider-policy-admission.mjs +3 -1
- package/lib/rdap-bootstrap.mjs +76 -16
- package/lib/rdap-client.mjs +20 -12
- package/lib/rdap-normalization.mjs +306 -75
- package/lib/rdap-transport.mjs +2 -2
- package/lib/rdap-validation.mjs +65 -14
- package/lib/rdap.mjs +2 -2
- package/lib/registrable-domain.mjs +36 -0
- package/lib/registry-insights.mjs +7 -0
- package/lib/response-policy.mjs +27 -4
- package/lib/risk-calibration-summary.mjs +35 -33
- package/lib/risk-scoring.mjs +4 -3
- package/lib/safe-fetch.mjs +62 -40
- package/lib/security-txt.mjs +1 -1
- package/lib/smtp-transport-review.mjs +8 -5
- package/lib/sslbl-intelligence.mjs +6 -8
- package/lib/static-html-analysis.mjs +301 -4
- package/lib/structured-data-identity.mjs +51 -19
- package/lib/threat-intelligence-fixtures.mjs +2 -4
- package/lib/threat-intelligence-manifests.mjs +2 -7
- package/lib/threat-intelligence-runtime.mjs +3 -5
- package/lib/threat-intelligence-types.mjs +3 -0
- package/lib/threatfox-intelligence.mjs +7 -3
- package/lib/tls-intelligence.mjs +4 -4
- package/lib/urlhaus-intelligence.mjs +4 -2
- package/lib/urlscan-intelligence.mjs +6 -5
- package/lib/website-security-posture.mjs +1 -1
- package/lib/website-technology.mjs +1 -1
- package/lib/whois-authority.mjs +43 -8
- package/lib/whois-chain.mjs +25 -3
- package/lib/whois-normalization.mjs +3 -1
- package/lib/whois-transport.mjs +12 -3
- package/lib/zone-intent-review.mjs +1 -1
- package/package.json +12 -4
- package/{frontend/src/lib/analysis/case-brand-profile-references.js → packages/cases/case-brand-profile-references.mjs} +2 -2
- package/{frontend/src/lib/analysis/case-evidence-model.js → packages/cases/case-evidence-model.mjs} +35 -14
- package/{frontend/src/lib/analysis/case-investigation-branch-model.js → packages/cases/case-investigation-branch-model.mjs} +10 -12
- package/packages/cases/case-migration-model.mjs +476 -0
- package/{frontend/src/lib/analysis/case-model.js → packages/cases/case-model.mjs} +3 -3
- package/{frontend/src/lib/analysis/case-record-contracts.js → packages/cases/case-record-contracts.mjs} +3 -21
- package/{frontend/src/lib/analysis/case-record-core.js → packages/cases/case-record-core.mjs} +58 -31
- package/packages/cases/case-record-model.mjs +9 -0
- package/{frontend/src/lib/analysis/case-record-operations.js → packages/cases/case-record-operations.mjs} +72 -29
- package/{frontend/src/lib/analysis/case-report.js → packages/cases/case-report.mjs} +108 -14
- package/packages/cases/case-response-model.mjs +1604 -0
- package/packages/cases/case-response-packet.mjs +1312 -0
- package/{frontend/src/lib/analysis/case-storage-model.js → packages/cases/case-storage-model.mjs} +2 -2
- package/{frontend/src/lib/analysis/http-summary.js → packages/cases/http-summary.mjs} +1 -1
- package/{frontend/src/lib/analysis/comparison-ledger-bulk.js → packages/comparison/comparison-ledger-bulk.mjs} +2 -2
- package/{frontend/src/lib/analysis/comparison-ledger-contract.js → packages/comparison/comparison-ledger-contract.mjs} +4 -4
- package/{frontend/src/lib/analysis/comparison-ledger-json.js → packages/comparison/comparison-ledger-json.mjs} +1 -0
- package/{frontend/src/lib/analysis/comparison-ledger-serialization.js → packages/comparison/comparison-ledger-serialization.mjs} +1 -0
- package/packages/comparison/favicon-similarity.mjs +78 -0
- package/{frontend/src/lib/analysis/page-similarity.js → packages/comparison/page-similarity.mjs} +4 -3
- package/{frontend/src/lib/analysis/relationship-evidence.js → packages/comparison/relationship-evidence.mjs} +6 -7
- package/packages/contracts/analyst-review-state-contract.mjs +61 -0
- package/packages/contracts/analyst-review-state.mjs +50 -0
- package/packages/contracts/case-portability.mjs +1310 -0
- package/packages/contracts/cli-command-catalogue.mjs +2 -0
- package/packages/contracts/cli-lookup.mjs +394 -0
- package/packages/contracts/domain-control-flight-recorder.mjs +461 -0
- package/packages/contracts/domain-control-manifest.mjs +1027 -0
- package/packages/contracts/domain-control-monitor.mjs +310 -0
- package/packages/contracts/domain-control-review.mjs +828 -0
- package/packages/contracts/domain-name.mjs +4 -0
- package/packages/contracts/external-observation-interchange.mjs +224 -0
- package/packages/contracts/extracted-domain-lifecycle.mjs +218 -0
- package/packages/contracts/investigation-portability.mjs +331 -0
- package/packages/contracts/offline-comparison.mjs +160 -0
- package/packages/contracts/risk-calibration.mjs +1288 -0
- package/packages/contracts/schema-compatibility.mjs +71 -0
- package/packages/contracts/schema-lifecycle.mjs +1702 -0
- package/packages/contracts/sslbl-snapshot.mjs +17 -0
- package/packages/contracts/workspace-portability.mjs +1347 -0
- package/{frontend/src/lib/analysis/artifact-integrity.js → packages/evidence/artifact-integrity.mjs} +13 -11
- package/packages/evidence/decision-fact.mjs +735 -0
- package/packages/evidence/domain-control-runtime.mjs +547 -0
- package/packages/evidence/domain-name.mjs +41 -0
- package/packages/evidence/observation.mjs +384 -0
- package/{frontend/src/lib/analysis/external-findings-import.js → packages/interchange/external-findings-import.mjs} +24 -22
- package/packages/interchange/retained-text.mjs +8 -0
- package/{frontend/src/lib/analysis/acquisition-decision-packet.js → packages/investigation/acquisition-decision-packet.mjs} +9 -6
- package/{frontend/src/lib/analysis/bulk-domain-comparison.js → packages/investigation/bulk-domain-comparison.mjs} +5 -6
- package/{frontend/src/lib/analysis/bulk-mail-exposure.js → packages/investigation/bulk-mail-exposure.mjs} +4 -6
- package/{frontend/src/lib/analysis/bulk-review-export.js → packages/investigation/bulk-review-export.mjs} +5 -5
- package/packages/investigation/bulk-review-policy.mjs +1 -0
- package/{frontend/src/lib/analysis/investigation-capsule.js → packages/investigation/investigation-capsule.mjs} +30 -32
- package/packages/investigation/lookup-artefact-inputs.mjs +1 -0
- package/{frontend/src/lib/analysis/lookup-asset-graph.js → packages/investigation/lookup-asset-graph.mjs} +4 -2
- package/{frontend/src/lib/analysis/lookup-claim-passport.js → packages/investigation/lookup-claim-passport.mjs} +6 -10
- package/{frontend/src/lib/analysis/lookup-claim-readiness.js → packages/investigation/lookup-claim-readiness.mjs} +9 -2
- package/packages/investigation/lookup-investigation-brief.mjs +172 -0
- package/packages/monitoring/analyst-review-state.mjs +680 -0
- package/{frontend/src/lib/analysis/brand-profile-model.js → packages/workspace/brand-profile-model.mjs} +70 -47
- package/{frontend/src/lib/analysis/bulk-review-model.js → packages/workspace/bulk-review-model.mjs} +13 -14
- package/{frontend/src/lib/analysis/bulk-session-model.js → packages/workspace/bulk-session-model.mjs} +33 -59
- package/{frontend/src/lib/analysis/bulk-sort.js → packages/workspace/bulk-sort.mjs} +8 -5
- package/{frontend/src/lib/analysis/campaign-model.js → packages/workspace/campaign-model.mjs} +20 -22
- package/{frontend/src/lib/analysis/detection-rule-model.js → packages/workspace/detection-rule-model.mjs} +15 -17
- package/packages/workspace/hostile-input.mjs +172 -0
- package/{frontend/src/lib/analysis/investigation-guide.js → packages/workspace/investigation-guide.mjs} +8 -45
- package/{frontend/src/lib/analysis/investigation-template-model.js → packages/workspace/investigation-template-model.mjs} +18 -21
- package/{frontend/src/lib/analysis/page-baseline.js → packages/workspace/page-baseline.mjs} +6 -13
- package/{frontend/src/lib/analysis/relationship-observation-model.js → packages/workspace/relationship-observation-model.mjs} +13 -17
- package/{frontend/src/lib/analysis/shortlist-model.js → packages/workspace/shortlist-model.mjs} +20 -18
- package/{frontend/src/lib/analysis/watchlist-history.js → packages/workspace/watchlist-history.mjs} +9 -16
- package/{frontend/src/lib/analysis/watchlist-store.js → packages/workspace/watchlist-store.mjs} +24 -17
- package/{frontend/src/lib/analysis/website-snapshot-model.js → packages/workspace/website-snapshot-model.mjs} +13 -13
- package/{frontend/src/lib/analysis/workspace-archive-crypto.js → packages/workspace/workspace-archive-crypto.mjs} +49 -19
- package/{frontend/src/lib/analysis/workspace-archive.js → packages/workspace/workspace-archive.mjs} +110 -89
- package/third-party-notices.txt +14 -14
- package/frontend/src/lib/analysis/bulk-retry-plan.js +0 -79
- package/frontend/src/lib/analysis/bulk-source-coverage.js +0 -76
- package/frontend/src/lib/analysis/case-migration-model.js +0 -305
- package/frontend/src/lib/analysis/case-record-model.js +0 -9
- package/frontend/src/lib/analysis/case-response-model.js +0 -728
- package/frontend/src/lib/analysis/case-response-packet.js +0 -583
- package/frontend/src/lib/analysis/lookup-decision-support.js +0 -542
- package/frontend/src/lib/analysis/lookup-investigation-brief.js +0 -153
- package/frontend/src/lib/analysis/lookup-presentation.js +0 -120
- package/frontend/src/lib/analysis/lookup-response.js +0 -2
- package/frontend/src/lib/analysis/lookup-source-refresh.js +0 -277
- package/frontend/src/lib/analysis/lookup-summary-model.js +0 -398
- package/frontend/src/lib/analysis/scoring.js +0 -55
- package/frontend/src/lib/analysis/utils.js +0 -255
- package/frontend/src/lib/analysis/visualization-bounds.js +0 -26
- package/frontend/src/lib/analysis/visualization-force-graph.js +0 -352
- package/frontend/src/lib/analysis/visualization-matrix.js +0 -131
- package/frontend/src/lib/analysis/visualization-models.js +0 -338
- package/frontend/src/lib/analysis/visualization-time-series.js +0 -185
- package/lib/bounded-json-response.mjs +0 -170
- package/lib/lookup-response-contract.mjs +0 -1034
- package/lib/observation.mjs +0 -115
- /package/{frontend/src/lib/analysis/opaque-reference-id.js → packages/cases/opaque-reference-id.mjs} +0 -0
- /package/{frontend/src/lib/analysis/acquisition-due-diligence.js → packages/investigation/acquisition-due-diligence.mjs} +0 -0
- /package/{frontend/src/lib/analysis/evidence-coverage-ledger.js → packages/investigation/evidence-coverage-ledger.mjs} +0 -0
- /package/{frontend/src/lib/analysis/dns-record-normalization.js → packages/workspace/dns-record-normalization.mjs} +0 -0
package/docs/cli-reference.md
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
# WHOISleuth CLI reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
The WHOISleuth CLI runs locally. Installed `whoisleuth <command> --help`,
|
|
4
|
+
`whoisleuth commands` and `whoisleuth manual` are the exact grammar, option and
|
|
5
|
+
command authorities for that installed version. The public
|
|
6
|
+
[CLI reference](https://whoisleuth.com/cli) provides a searchable view generated
|
|
7
|
+
from the same registry.
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`whoisleuth --help` displays the copyright, AGPL-3.0-only licence, and official
|
|
11
|
-
source location. It groups commands by investigation, discovery, saved-evidence,
|
|
12
|
-
integrity, and calibration workflows. `whoisleuth <command> --help` displays the
|
|
13
|
-
command's purpose, focused invocation, example, and collection boundary without
|
|
14
|
-
printing the full command list. `whoisleuth commands --json` exposes those same
|
|
15
|
-
contracts as a stable local catalogue for wrappers and terminal tooling.
|
|
16
|
-
Packaged copies include `LICENSE`, `NOTICE`, and
|
|
17
|
-
`TRADEMARKS.md` alongside the CLI documentation.
|
|
9
|
+
This page records the common interfaces and the boundaries that matter across
|
|
10
|
+
commands. The generated [privacy/data-flow catalogue](https://github.com/slicedearth/whoisleuth/blob/main/docs/privacy-data-flow-catalogue.md)
|
|
11
|
+
contains the exhaustive recipient, retention and export metadata.
|
|
18
12
|
|
|
19
13
|
## Installation
|
|
20
14
|
|
|
21
|
-
Public releases require Node.js 24 or later
|
|
22
|
-
command:
|
|
15
|
+
Public releases require Node.js 24 or later:
|
|
23
16
|
|
|
24
17
|
```bash
|
|
25
18
|
npm exec --yes --ignore-scripts --package=@slicedearth/whoisleuth-cli -- whoisleuth --help
|
|
@@ -27,1703 +20,127 @@ npm install --global --ignore-scripts @slicedearth/whoisleuth-cli
|
|
|
27
20
|
whoisleuth doctor
|
|
28
21
|
```
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
whoisleuth --version
|
|
35
|
-
```
|
|
23
|
+
The scoped package and application share one semantic version. The package
|
|
24
|
+
requires no dependency lifecycle scripts and does not call the hosted
|
|
25
|
+
WHOISleuth deployment. From a repository checkout, replace `whoisleuth` with
|
|
26
|
+
`node bin/whoisleuth.mts`.
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
locally and does not call the hosted WHOISleuth deployment. Networked commands
|
|
39
|
-
contact only the sources described by their collection profile; offline review,
|
|
40
|
-
comparison, verification, completion, and manual commands remain local.
|
|
41
|
-
|
|
42
|
-
## Commands
|
|
28
|
+
## Find and inspect commands
|
|
43
29
|
|
|
44
30
|
```bash
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
node bin/whoisleuth.mts lookup example.com --deep --summary
|
|
51
|
-
node bin/whoisleuth.mts lookup example.com --deep --verbose
|
|
52
|
-
node bin/whoisleuth.mts lookup example.com --deep --markdown --output lookup.md
|
|
53
|
-
node bin/whoisleuth.mts lookup example.com --deep --json --strict-exit --events
|
|
54
|
-
node bin/whoisleuth.mts lookup example.test --deep --observer workstation-a --vantage office-egress --json > office.json
|
|
55
|
-
cat domains.txt | node bin/whoisleuth.mts bulk --jsonl
|
|
56
|
-
node bin/whoisleuth.mts bulk domains.txt --csv --registered-only
|
|
57
|
-
node bin/whoisleuth.mts bulk domains.txt --domains --inconclusive-only
|
|
58
|
-
node bin/whoisleuth.mts bulk domains.txt --queries --errors-only
|
|
59
|
-
node bin/whoisleuth.mts bulk domains.txt --concurrency 4
|
|
60
|
-
node bin/whoisleuth.mts bulk domains.txt --deep --checkpoint bulk-checkpoint.json
|
|
61
|
-
node bin/whoisleuth.mts bulk domains.txt --deep --checkpoint bulk-checkpoint.json --resume
|
|
62
|
-
node bin/whoisleuth.mts ct-search 'example brand' --json
|
|
63
|
-
node bin/whoisleuth.mts discover example.com --preset common --jsonl
|
|
64
|
-
node bin/whoisleuth.mts discover example.test --dictionary private-terms.txt --snapshot discovery-state.json --json
|
|
65
|
-
node bin/whoisleuth.mts discover-scan example.test --scan-limit 50 --checkpoint candidate-scan.json --json
|
|
66
|
-
node bin/whoisleuth.mts discover-scan example.test --deep --scan-limit 20 --resolver <public-resolver-ip> --observation-snapshot observed-candidates.json --csv
|
|
67
|
-
node bin/whoisleuth.mts posture example.com --selectors selector1 --retired-selectors selector0 --mail-profile defensive-no-mail --json
|
|
68
|
-
node bin/whoisleuth.mts http example.com --json
|
|
69
|
-
node bin/whoisleuth.mts tls example.com --json
|
|
70
|
-
node bin/whoisleuth.mts registry-support example.uk --json
|
|
71
|
-
node bin/whoisleuth.mts registry-doctor lookup.json --json
|
|
72
|
-
node bin/whoisleuth.mts registry-cohort saved-lookups.jsonl --json
|
|
73
|
-
node bin/whoisleuth.mts registry-scaffold --profile example-profile --suffix test --scenario registered
|
|
74
|
-
node bin/whoisleuth.mts risk-calibrate calibration.json --json
|
|
75
|
-
node bin/whoisleuth.mts risk-calibrate calibration.json --summary-json
|
|
76
|
-
node bin/whoisleuth.mts lookalike-calibrate reviewed-candidates.json --json
|
|
77
|
-
node bin/whoisleuth.mts verify-artifact workspace.json --json
|
|
78
|
-
node bin/whoisleuth.mts verify-artifact lookup.json --json --strict-exit
|
|
79
|
-
node bin/whoisleuth.mts verify-artifact workspace-encrypted.json --passphrase-file passphrase.txt --json
|
|
80
|
-
node bin/whoisleuth.mts source-report lookup.json --json
|
|
81
|
-
node bin/whoisleuth.mts inspect-archive workspace.json --json
|
|
82
|
-
node bin/whoisleuth.mts inspect-archive workspace.json --search example.invalid --json
|
|
83
|
-
node bin/whoisleuth.mts sign-artifact response-packet.json --private-key-file analyst-private.pem > response-packet.signed.json
|
|
84
|
-
node bin/whoisleuth.mts ct-intake certificate-events.json --json > external-findings.json
|
|
85
|
-
node bin/whoisleuth.mts map-observations observation-mapping.json --json > external-findings.json
|
|
86
|
-
node bin/whoisleuth.mts oam-export external-findings.json --json > asset-bridge.json
|
|
87
|
-
node bin/whoisleuth.mts manifest lookup.json comparison.json --workflow 'domain review' --json > investigation-manifest.json
|
|
88
|
-
node bin/whoisleuth.mts verify-signature response-packet.signed.json --public-key-file analyst-public.pem
|
|
89
|
-
node bin/whoisleuth.mts lookup example.com --deep --json > lookup.json
|
|
90
|
-
node bin/whoisleuth.mts compare lookup.json --json
|
|
91
|
-
node bin/whoisleuth.mts page-compare official.json candidate.json --json
|
|
92
|
-
node bin/whoisleuth.mts mail-review bulk.json --json
|
|
93
|
-
node bin/whoisleuth.mts dnssec-validate example.test --resolver "$PUBLIC_RESOLVER_IP" --trust-anchor anchor.json --owned-or-authorized --json
|
|
94
|
-
node bin/whoisleuth.mts mail-transport selected-mx.json --resolver "$PUBLIC_RESOLVER_IP" --trust-anchor anchor.json --owned-or-authorized --active-probe --json
|
|
95
|
-
node bin/whoisleuth.mts review-evidence dnssec-evidence.json --json
|
|
96
|
-
node bin/whoisleuth.mts review-evidence trust-store-comparison.json --json
|
|
97
|
-
node bin/whoisleuth.mts domain-control domain-control-input.json --json
|
|
98
|
-
node bin/whoisleuth.mts assurance domain-assurance-input.json --json
|
|
99
|
-
node bin/whoisleuth.mts change-packet domain-change-packet-input.json --json
|
|
100
|
-
node bin/whoisleuth.mts sharing-review response-packet.json --marking amber --recipient-scope organization --purpose 'Reviewed incident handoff' --human-reviewed --personal-data-reviewed --redactions-confirmed --json
|
|
101
|
-
node bin/whoisleuth.mts workflow-plan domain-triage example.test --json
|
|
102
|
-
node bin/whoisleuth.mts workflow-run domain-triage example.test --approve-network --json --output run.json
|
|
103
|
-
node bin/whoisleuth.mts brief lookup.json
|
|
104
|
-
node bin/whoisleuth.mts case-pack cases.json --audience trusted --reviewed --json
|
|
105
|
-
node bin/whoisleuth.mts monitor-once control-manifest.json --previous prior-control.json --junit
|
|
106
|
-
node bin/whoisleuth.mts diff first-lookup.json second-lookup.json --json
|
|
107
|
-
node bin/whoisleuth.mts reconcile office.json mobile.json external.json --json
|
|
108
|
-
node bin/whoisleuth.mts timeline first-observation.json second-observation.json latest-observation.json --json
|
|
109
|
-
node bin/whoisleuth.mts export lookup.json > evidence.json
|
|
110
|
-
node bin/whoisleuth.mts export lookup.json --markdown > evidence.md
|
|
111
|
-
node bin/whoisleuth.mts export lookup.json --html > evidence.html
|
|
112
|
-
node bin/whoisleuth.mts doctor
|
|
113
|
-
node bin/whoisleuth.mts doctor --network --json
|
|
114
|
-
node bin/whoisleuth.mts commands --json
|
|
115
|
-
node bin/whoisleuth.mts completion zsh
|
|
116
|
-
node bin/whoisleuth.mts completion powershell
|
|
117
|
-
node bin/whoisleuth.mts manual | man -l -
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
These examples run from a checked-out repository; replace
|
|
121
|
-
`node bin/whoisleuth.mts` with `whoisleuth` after installation. The root
|
|
122
|
-
application package remains private. A separate scoped CLI archive is assembled
|
|
123
|
-
from the exact executable dependency closure, installed in a temporary
|
|
124
|
-
directory, and smoke tested with:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
npm run cli:package:check
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
The check includes only the executable, reachable TypeScript modules, CLI
|
|
131
|
-
guide, licence, notices, and trademark terms. It excludes application routes,
|
|
132
|
-
deployment adapters, tests, and development tools. Direct runtime dependencies
|
|
133
|
-
are pinned to the exact versions exercised by the reviewed repository lockfile.
|
|
134
|
-
The package and its dependencies require no lifecycle scripts, so the install
|
|
135
|
-
examples disable them explicitly.
|
|
136
|
-
Its generated manifest stays private. Release-candidate assembly is a separate
|
|
137
|
-
explicit operation and never publishes from a developer checkout. Use the
|
|
138
|
-
scoped package name; an unqualified `npx whoisleuth` is not this project.
|
|
139
|
-
|
|
140
|
-
Lookup defaults to the conservative fast profile. `--deep` must be requested
|
|
141
|
-
explicitly and can add bounded WHOIS, DNS, website, TLS, registrar RDAP, and
|
|
142
|
-
observed-network IP RDAP work for a domain. The browser Console's optional
|
|
143
|
-
security.txt and external intelligence selections are not CLI flags; the CLI
|
|
144
|
-
does not run those actions implicitly.
|
|
145
|
-
|
|
146
|
-
For a directly entered public IP address, `lookup --deep` can also run one
|
|
147
|
-
bounded reverse-DNS query. Terminal output shows the explicit source state and
|
|
148
|
-
up to five normalised PTR names; JSON retains up to eight. PTR names are
|
|
149
|
-
operator-published routing context, not proof of hosting control or ownership.
|
|
150
|
-
Fast lookups do not run this query.
|
|
151
|
-
|
|
152
|
-
`lookup --plan` performs classification and prints a versioned preflight without
|
|
153
|
-
starting collection. It lists the normalised target, selected fast or deep
|
|
154
|
-
mode, planned source families, conditional operations, and the data each family
|
|
155
|
-
may receive. The plan cannot predict live feature configuration, cache state,
|
|
156
|
-
redirects, referrals, source availability, or an exact request count. It can be
|
|
157
|
-
combined with `--json`, but not with report, detail, strict-exit, progress-event,
|
|
158
|
-
or quiet options.
|
|
159
|
-
|
|
160
|
-
Only one query is accepted by `lookup`. Multiple-input processing belongs to
|
|
161
|
-
the explicit `bulk` command rather than being silently inferred by `lookup`.
|
|
162
|
-
Standard input is capped at 4 KiB and must contain one non-empty line.
|
|
163
|
-
|
|
164
|
-
`registry-support` is an offline catalogue view. It accepts one domain, bare
|
|
165
|
-
suffix, or leading-dot suffix as an argument or on stdin and makes no network
|
|
166
|
-
request. Its output is described below.
|
|
167
|
-
|
|
168
|
-
`doctor` is offline by default. It checks the Node runtime, platform, terminal
|
|
169
|
-
capabilities, and availability of offline command families. `doctor --network`
|
|
170
|
-
adds independent bounded public-DNS, HTTPS/RDAP bootstrap, and WHOIS port 43
|
|
171
|
-
checks against fixed IANA diagnostic infrastructure. The three probes run
|
|
172
|
-
within the same per-probe ceiling so one stalled transport does not block the
|
|
173
|
-
others. The report retains only state, HTTP status, and a bounded explanation,
|
|
174
|
-
not resolved addresses or response content. A failed optional network check
|
|
175
|
-
returns the partial-failure exit code rather than claiming that all CLI
|
|
176
|
-
collection is unavailable.
|
|
177
|
-
|
|
178
|
-
`completion bash`, `completion zsh`, `completion fish`, and `completion
|
|
179
|
-
powershell` print static shell completion scripts to stdout. The command does
|
|
180
|
-
not edit a shell profile or make a network request. Review the generated script
|
|
181
|
-
before sourcing it or placing it in the relevant shell completion directory.
|
|
182
|
-
`manual` prints a generated roff manual page and likewise changes no local
|
|
183
|
-
configuration.
|
|
184
|
-
|
|
185
|
-
`commands` prints the installed command catalogue without running collection or
|
|
186
|
-
reading evidence. `commands --json` emits version 1 of the
|
|
187
|
-
`whoisleuth.cli.command-catalogue` schema, including each command's usage,
|
|
188
|
-
example, declared collection mode, collection scope, and boundary. This is the
|
|
189
|
-
supported discovery contract for local wrappers; it is not a permission grant
|
|
190
|
-
or a substitute for focused help.
|
|
191
|
-
|
|
192
|
-
Focused command help and the generated manual classify every operation as
|
|
193
|
-
offline or networked and state the relevant target, input, and concurrency
|
|
194
|
-
ceiling. These labels describe observable behaviour rather than granting
|
|
195
|
-
authorisation. The packaged `DISCLOSURE` defines the intended defensive scope;
|
|
196
|
-
operators remain responsible for law, provider terms, and authorisation.
|
|
197
|
-
|
|
198
|
-
## Deployment boundary
|
|
199
|
-
|
|
200
|
-
The CLI runs locally. The serverless deployment publishes only `frontend/build`
|
|
201
|
-
and packages functions only from `netlify/functions`, so `bin/` and `cli/` are
|
|
202
|
-
not part of the hosted static site or function bundle. The application root and
|
|
203
|
-
ordinary package-check candidate remain private. Explicitly reviewed CLI
|
|
204
|
-
release candidates can be published under the scoped public package described
|
|
205
|
-
in the installation section.
|
|
206
|
-
|
|
207
|
-
Commands that query RDAP, WHOIS, DNS, HTTP, TLS, SMTP, or Certificate Transparency do
|
|
208
|
-
so directly from the machine running the CLI. They do not use the hosted login,
|
|
209
|
-
hosted session, or deployment usage controls; upstream providers can see and
|
|
210
|
-
rate-limit the local machine's network address. Offline `discover`, `compare`,
|
|
211
|
-
`page-compare`, `mail-review`, `review-evidence`, `domain-control`, `assurance`, `change-packet`,
|
|
212
|
-
`sharing-review`, `workflow-plan`, `brief`, `case-pack`, `registry-cohort`,
|
|
213
|
-
`registry-scaffold`, `diff`, `reconcile`, `timeline`,
|
|
214
|
-
`risk-calibrate`, `lookalike-calibrate`, `registry-doctor`, `verify-artifact`, `source-report`,
|
|
215
|
-
`map-observations`, `oam-export`, `export`,
|
|
216
|
-
`commands`, `completion`, and `manual` operations make no network requests. Commands write
|
|
217
|
-
to stdout unless the analyst deliberately selects a local output file.
|
|
218
|
-
|
|
219
|
-
Path operands are opened through one bounded regular-file boundary. Named
|
|
220
|
-
pipes, devices and directories are refused without waiting for a writer;
|
|
221
|
-
symbolic links to regular analyst-selected files remain supported. Standard
|
|
222
|
-
input is the only intentional streaming input and observes the same command
|
|
223
|
-
byte limit and cancellation signal.
|
|
224
|
-
|
|
225
|
-
## Output
|
|
226
|
-
|
|
227
|
-
Human-readable terminal output is the default. On an interactive terminal it
|
|
228
|
-
uses restrained semantic colour, groups Lookup evidence by purpose, wraps
|
|
229
|
-
prose to the detected terminal width, and shows transient progress on stderr
|
|
230
|
-
for slower collection. State remains explicit in text, so colour is never the
|
|
231
|
-
only distinction. Redirected terminal output, JSON, and JSONL contain no ANSI
|
|
232
|
-
sequences or progress text. `--no-color` and a non-empty conventional
|
|
233
|
-
`NO_COLOR` environment variable disable colour; `WHOISLEUTH_NO_PROGRESS=1`
|
|
234
|
-
disables the transient indicator. Command examples remain one copyable line
|
|
235
|
-
even when prose is wrapped for a narrow terminal.
|
|
236
|
-
|
|
237
|
-
Every command accepts `--output <file>` as a safer alternative to shell
|
|
238
|
-
redirection. WHOISleuth buffers bounded output, creates a private temporary file
|
|
239
|
-
beside the destination, syncs it, and publishes it atomically with mode `0600`.
|
|
240
|
-
An existing destination is refused. `--force` is valid only with `--output` and
|
|
241
|
-
allows an intentional atomic replacement. A failed or cancelled command does
|
|
242
|
-
not publish a partial output file. Output is capped at 32 MiB.
|
|
243
|
-
|
|
244
|
-
`--config <file> --profile <name>` reads a strict version-1 local configuration
|
|
245
|
-
document of at most 64 KiB. Without `--config`, the path is
|
|
246
|
-
`$XDG_CONFIG_HOME/whoisleuth/config.json`. A profile may contain no more than
|
|
247
|
-
16 safe defaults drawn from `--no-color`, `--summary`, `--verbose`, `--fast`,
|
|
248
|
-
`--concurrency`, `--observer`, and `--vantage`. It cannot supply a target,
|
|
249
|
-
Deep mode, output path, network approval, failure policy, credential, or
|
|
250
|
-
arbitrary argument. Explicit command options override profile defaults from
|
|
251
|
-
the same group.
|
|
252
|
-
|
|
253
|
-
Lookup, Bulk, and `monitor-once` can emit bounded JUnit XML. Owned-domain
|
|
254
|
-
Posture can emit SARIF only when `--owned-domain` confirms the passive target
|
|
255
|
-
boundary. The reports contain categorical source or posture findings rather
|
|
256
|
-
than raw evidence. Supported network commands accept an explicit comma-
|
|
257
|
-
separated `--fail-on` policy from `source-failure`, `inconclusive`, `danger`,
|
|
258
|
-
and `material-drift`; a match returns the partial-result exit code after the
|
|
259
|
-
normal output is emitted.
|
|
260
|
-
|
|
261
|
-
`lookup --markdown` and `lookup --html` build the existing normalised evidence
|
|
262
|
-
report directly after one completed domain lookup. They do not start a second
|
|
263
|
-
collection. These report formats reject IP and ASN inputs before collection;
|
|
264
|
-
JSON and terminal output remain available for those query types. Both readable
|
|
265
|
-
formats include a fixed local generator footer by default. `--no-attribution`
|
|
266
|
-
removes that presentation-only footer without changing evidence-source
|
|
267
|
-
attribution, generator metadata in JSON, or collection behaviour.
|
|
268
|
-
|
|
269
|
-
Lookup terminal output supports three detail levels. The standard view keeps
|
|
270
|
-
the normal bounded evidence summary. `--summary` keeps the source states and
|
|
271
|
-
key findings while omitting endpoints and supporting detail. `--verbose` adds
|
|
272
|
-
the document generation time and the existing bounded per-source collection
|
|
273
|
-
timings. These switches are presentation-only and cannot be combined with
|
|
274
|
-
`--json`; they do not change collection or the result document.
|
|
275
|
-
|
|
276
|
-
`--json` writes one versioned document to standard output:
|
|
277
|
-
|
|
278
|
-
```json
|
|
279
|
-
{
|
|
280
|
-
"schema": "whoisleuth.cli.lookup",
|
|
281
|
-
"version": 1,
|
|
282
|
-
"generatedAt": "2026-07-14T00:00:00.000Z",
|
|
283
|
-
"mode": "fast",
|
|
284
|
-
"query": "example.com",
|
|
285
|
-
"type": "domain"
|
|
286
|
-
}
|
|
31
|
+
whoisleuth --help
|
|
32
|
+
whoisleuth commands --common
|
|
33
|
+
whoisleuth commands --group investigate --mode network
|
|
34
|
+
whoisleuth lookup --help
|
|
35
|
+
whoisleuth lookup example.test --deep --plan --json
|
|
287
36
|
```
|
|
288
37
|
|
|
289
|
-
The
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
partial final result, flushes an enabled Bulk checkpoint, and exits with code
|
|
345
|
-
130. SIGTERM follows the same graceful cleanup path and exits with code 143.
|
|
346
|
-
Already started network operations remain subject to their existing hard
|
|
347
|
-
timeouts while the shared in-process API unwinds; the executable terminates
|
|
348
|
-
after CLI cleanup. A second Ctrl-C removes any known unpublished temporary
|
|
349
|
-
output file on a best-effort basis before exiting immediately.
|
|
350
|
-
|
|
351
|
-
Bulk can persist compact progress with `--checkpoint <file>`. A new checkpoint
|
|
352
|
-
is private, bounded to 16 MiB, versioned, and tied to the exact ordered input
|
|
353
|
-
and scan mode by SHA-256. It stores only compact per-item results, never full
|
|
354
|
-
Lookup responses. Checkpoint schema 2 records a nullable per-row observation
|
|
355
|
-
time. Schema 1 remains readable, but its resumed rows keep observation time
|
|
356
|
-
unknown rather than inheriting the resume time. Reusing the same path is
|
|
357
|
-
refused unless `--resume` is also
|
|
358
|
-
specified. Resume revalidates the complete untrusted document and skips only
|
|
359
|
-
the exact completed rows; changed input, mode, schema, digest, or malformed
|
|
360
|
-
results fail closed.
|
|
361
|
-
|
|
362
|
-
Bulk JSON, JSONL, and item documents use schema version 3. Each row includes
|
|
363
|
-
`observedAt` and a `collectionOrigin` of `current_run` or
|
|
364
|
-
`resumed_checkpoint`; the top-level `generatedAt` remains the report creation
|
|
365
|
-
time. HTTP JSON uses schema version 2 and adds the explicit `assessment` field.
|
|
366
|
-
The legacy `activityStatus` field remains for compatibility, but is `null`
|
|
367
|
-
when collection is inconclusive rather than labelling the target unreachable.
|
|
368
|
-
Consumers should use `assessment`; older version-1 `unreachable` values remain
|
|
369
|
-
historical inconclusive labels, not proof that a target cannot be reached.
|
|
370
|
-
|
|
371
|
-
If checkpoint persistence fails after collection, WHOISleuth still emits the
|
|
372
|
-
completed final result, reports the checkpoint limitation, and exits with code
|
|
373
|
-
4. The last successfully published checkpoint remains available, but it may
|
|
374
|
-
not contain the final completed items.
|
|
375
|
-
|
|
376
|
-
`diff <left.json> <right.json>` compares two compatible retained artefacts
|
|
377
|
-
entirely offline. Saved Lookup documents keep their version-1 lookup-diff
|
|
378
|
-
output. Portable Bulk-session exports and domain-portfolio reviews emit a
|
|
379
|
-
`whoisleuth.cli.comparison-ledger` version-1 document with a value-free bounded
|
|
380
|
-
index and at most 256 exact detail rows. Bulk exports containing more than one
|
|
381
|
-
session require `--left-session <id>` or `--right-session <id>` as applicable.
|
|
382
|
-
The command keeps missing, unavailable, equal, added, and different evidence
|
|
383
|
-
separate, treats later portfolio omission as incomplete rather than removal,
|
|
384
|
-
and retains no input path. It makes no ownership, safety, or maliciousness
|
|
385
|
-
inference.
|
|
386
|
-
|
|
387
|
-
`lookup --observer <label> --vantage <label>` can add two bounded analyst labels
|
|
388
|
-
to a saved Lookup document. The labels identify the person or process that ran
|
|
389
|
-
the observation and the collection context chosen by that analyst; they are
|
|
390
|
-
not verified identities, network measurements, or proof of independent
|
|
391
|
-
collection. They do not change which sources are queried.
|
|
392
|
-
|
|
393
|
-
`reconcile <observation.json> <observation.json> [...]` accepts from 2 to 5
|
|
394
|
-
saved Lookup documents for the same domain and compares their bounded fields
|
|
395
|
-
offline. It keeps agreement, disagreement, and non-comparable evidence
|
|
396
|
-
separate, retains observation times and optional analyst labels, and copies no
|
|
397
|
-
filenames or raw registration payloads. Distinct complete label pairs are
|
|
398
|
-
reported as labelled collection contexts only; majority agreement is not
|
|
399
|
-
treated as truth or authority.
|
|
400
|
-
|
|
401
|
-
`timeline <observation.json> <observation.json> [...]` accepts from 2 to 20
|
|
402
|
-
saved Lookup documents for one domain, orders them by their validated
|
|
403
|
-
observation times, and compares each adjacent pair offline. The 32 MiB aggregate
|
|
404
|
-
input ceiling is enforced while files are read and again by the timeline
|
|
405
|
-
builder. Output retains normalised field states and observation times but no
|
|
406
|
-
input filenames or raw registry payloads. A difference can reflect a domain
|
|
407
|
-
change or changed collection conditions, so the command makes no current-state,
|
|
408
|
-
ownership, intent, safety, or maliciousness conclusion.
|
|
409
|
-
|
|
410
|
-
When diagnostics version 5, 6, 7, or 8 reports a documented registry collection
|
|
411
|
-
constraint, terminal output also shows the suffix, WHOIS and RDAP access
|
|
412
|
-
profiles, and the bounded limitation. This is static access-policy context: it
|
|
413
|
-
does not make another request, and restricted, unpublished, or unavailable
|
|
414
|
-
machine access is not evidence that a domain is unregistered or safe.
|
|
415
|
-
|
|
416
|
-
## Exit codes
|
|
38
|
+
The command index groups work under Investigate, Respond, Assure and Utilities.
|
|
39
|
+
Filters combine by intersection. `commands --json` emits the versioned local
|
|
40
|
+
catalogue without reading evidence or running the selected commands.
|
|
41
|
+
|
|
42
|
+
An eligible domain, reserved documentation domain, IP address or ASN can occupy
|
|
43
|
+
command position as Lookup shorthand. Use explicit `lookup` where input needs
|
|
44
|
+
supported URL-like normalisation. Credentials, paths, queries, fragments, ports
|
|
45
|
+
and unsupported special-use targets are rejected by the shorthand.
|
|
46
|
+
|
|
47
|
+
`registry-scaffold` has a separate fixture contract: its `--profile` selects one
|
|
48
|
+
fixed fixture profile and shared `--config` profiles are rejected. It produces
|
|
49
|
+
sanitised local fixture material and makes no registry request.
|
|
50
|
+
|
|
51
|
+
## Requests and authorisation
|
|
52
|
+
|
|
53
|
+
Offline commands read only supplied arguments, files, standard input and
|
|
54
|
+
installed catalogues. Networked commands contact the sources named by their
|
|
55
|
+
focused help; those sources can observe and rate-limit the operator's network
|
|
56
|
+
address. The CLI does not inherit hosted login, provider configuration or
|
|
57
|
+
hosted operation limits.
|
|
58
|
+
|
|
59
|
+
`lookup --plan` classifies a target and lists intended source families and
|
|
60
|
+
disclosures without collecting. Fast is the Lookup default. Deep adds the
|
|
61
|
+
applicable registration, DNS, HTTP, TLS, page, technology and network context.
|
|
62
|
+
Optional browser providers are not implicit CLI actions.
|
|
63
|
+
|
|
64
|
+
`dnssec-validate` and `mail-transport` are isolated authorised actions. Both
|
|
65
|
+
require a selected literal public resolver, a local trust-anchor document and
|
|
66
|
+
`--owned-or-authorized`; mail transport also requires `--active-probe`. Mail
|
|
67
|
+
transport handles at most three selected MX hosts sequentially, sends `EHLO`
|
|
68
|
+
and uses `STARTTLS` only when advertised. It does not send mail, authenticate,
|
|
69
|
+
test relay, enumerate recipients or retry automatically. DNSSEC, TLSA/DANE,
|
|
70
|
+
PKIX, STARTTLS and SMTP transport remain separate evidence states.
|
|
71
|
+
|
|
72
|
+
The repository-only rendered-capture package is outside hosted and distributable
|
|
73
|
+
collection. It executes remote page JavaScript only for an explicitly
|
|
74
|
+
authorised route set, and each admitted resource operator receives the exact
|
|
75
|
+
requested URL. Captures and screenshots remain local until the operator deletes
|
|
76
|
+
them.
|
|
77
|
+
|
|
78
|
+
## Files, output and automation
|
|
79
|
+
|
|
80
|
+
File inputs are bounded before parsing; directories, devices and named pipes are
|
|
81
|
+
refused. Output goes to the terminal unless a command supports `--output`.
|
|
82
|
+
Private output is written atomically and an existing path is refused unless
|
|
83
|
+
replacement is explicit.
|
|
84
|
+
|
|
85
|
+
Terminal text is the default. JSON, JSONL, CSV, Markdown, HTML and domain-only
|
|
86
|
+
formats are available only where the installed command declares them.
|
|
87
|
+
Redirected and machine output contains no ANSI or progress text. Diagnostics
|
|
88
|
+
and optional target-free `--events` output use standard error.
|
|
89
|
+
|
|
90
|
+
`--fail-on` and `--strict-exit` expose selected evidence states to automation
|
|
91
|
+
without changing the result document. Review focused help for the policies a
|
|
92
|
+
command supports.
|
|
417
93
|
|
|
418
94
|
| Code | Meaning |
|
|
419
95
|
| ---: | --- |
|
|
420
|
-
| 0 |
|
|
421
|
-
| 2 |
|
|
422
|
-
| 3 |
|
|
423
|
-
| 4 |
|
|
424
|
-
| 70 |
|
|
425
|
-
| 130 | The analyst cancelled
|
|
426
|
-
| 143 |
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
`
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
version-1/version-2 reports. It emits version 2 with target-free suffix and
|
|
472
|
-
capability-profile timelines, an explicit sample window, retained-report count,
|
|
473
|
-
and at most 50 visible points per cohort. A version-1 report becomes one
|
|
474
|
-
retained point. A cohort with fewer than five samples remains insufficient,
|
|
475
|
-
and overlapping retained samples are never summed or promoted to independent
|
|
476
|
-
consistency. Domains, queries, filenames, and raw registry evidence are not
|
|
477
|
-
retained.
|
|
478
|
-
|
|
479
|
-
`registry-scaffold --profile <id> --suffix <suffix> --scenario <state>` emits
|
|
480
|
-
one bounded, sanitised synthetic fixture scaffold from the installed registry
|
|
481
|
-
catalogue. The three supported states are `registered`, `not_found`, and
|
|
482
|
-
`inconclusive`. It does not fetch a live response, include a real target, or
|
|
483
|
-
alter the embedded catalogue.
|
|
484
|
-
|
|
485
|
-
The offline RDAP supplied-evidence review implements the request shape defined
|
|
486
|
-
by RFC 9536 for `resources`, `domains`, `nameservers`, and `entities`. It also
|
|
487
|
-
validates a supplied server's `reverse_search_properties_mapping` response
|
|
488
|
-
before preparing a request. Only registered IANA property paths and exact
|
|
489
|
-
supported resource/property pairs are accepted. Preparing the request neither
|
|
490
|
-
proves that a particular server supports it nor sends a reverse search; active
|
|
491
|
-
execution remains gated on a reviewed server policy, privacy boundary, and
|
|
492
|
-
deterministic fixtures.
|
|
493
|
-
|
|
494
|
-
The separate maintenance command `npm run rdap-extensions:drift` compares the
|
|
495
|
-
pinned official RDAP extension fixture with the reviewed local interpretation
|
|
496
|
-
catalogue entirely offline. `--live` performs one bounded manual fetch from the
|
|
497
|
-
fixed official CSV URL and reports added, removed, renamed, status-changed,
|
|
498
|
-
unrecognized, and local-only identifiers. `--json` emits
|
|
499
|
-
`whoisleuth.rdap-extension-drift-audit` version 1. The manual live fetch keeps one
|
|
500
|
-
10-second deadline armed through the capped 128 KiB body read and fails closed if
|
|
501
|
-
the official CSV is truncated. Drift exits with status 1 and
|
|
502
|
-
requires specification and fixture review; the command never enables an
|
|
503
|
-
extension, changes authority or availability logic, or issues reverse search.
|
|
504
|
-
|
|
505
|
-
`npm run service-dependencies:audit` validates the passive service-dependency
|
|
506
|
-
catalogue entirely offline. It checks the catalogue digest, duplicate
|
|
507
|
-
identifiers and target suffixes, evidence classes, source and licence
|
|
508
|
-
treatment, source dates, and a fixed 180-day review age. `--json` emits
|
|
509
|
-
`whoisleuth.service-dependency-signature-audit` version 1. A stale or changed
|
|
510
|
-
signature requires manual provider and benign-fixture review; the command
|
|
511
|
-
never resolves a target, checks an account, or tests claimability.
|
|
512
|
-
|
|
513
|
-
## Offline Risk calibration
|
|
514
|
-
|
|
515
|
-
`risk-calibrate` replays a versioned analyst-labelled fixture dataset through
|
|
516
|
-
the exact Risk model shared with the web application. It does not perform a
|
|
517
|
-
lookup, contact the hosted deployment, persist the dataset, alter model weights,
|
|
518
|
-
choose a threshold, or tune the model automatically. The report compares fixed
|
|
519
|
-
thresholds from 40 through 90 and identifies 70 as the current review band. It
|
|
520
|
-
also reports F1, balanced accuracy, Wilson 95% intervals, deliberately small
|
|
521
|
-
scan-depth and review-reason strata, and a current-versus-previous model replay.
|
|
522
|
-
Strata with fewer than 20 included labels are marked insufficient rather than
|
|
523
|
-
presented as reliable performance estimates. Report version 3 distinguishes
|
|
524
|
-
the ordinary `detailed` output from the aggregate `summary` projection.
|
|
525
|
-
|
|
526
|
-
`--json` emits the bounded detailed report, including record identifiers,
|
|
527
|
-
domains, analyst dispositions, scores and factor summaries. Use
|
|
528
|
-
`--summary-json` for the target-free aggregate accepted by Monitor's local
|
|
529
|
-
calibration explorer. That projection retains only dataset and model versions,
|
|
530
|
-
aggregate class and score-band counts, fixed-threshold confusion metrics and
|
|
531
|
-
Wilson intervals, bounded strata, model-comparison counts, and an explicit
|
|
532
|
-
zero-target privacy declaration. It contains no record array, identifier,
|
|
533
|
-
domain, evidence field, factor, note or provider payload. Both forms remain
|
|
534
|
-
offline and are written only when the analyst deliberately selects an output.
|
|
535
|
-
|
|
536
|
-
The JSON report derives a bounded `interoperabilityTags` list from the
|
|
537
|
-
analyst-owned disposition and review reason. The mapping uses reviewed MISP
|
|
538
|
-
taxonomy terms only where the meaning is unambiguous. Tags do not change a
|
|
539
|
-
score, disposition, or case, and no MISP service is contacted.
|
|
540
|
-
|
|
541
|
-
Input is capped at 2 MiB and 500 records. Each record requires a unique bounded
|
|
542
|
-
ID, an ASCII DNS hostname, one existing analyst disposition, and a strict
|
|
543
|
-
whitelist of current scoring inputs. Unknown fields are discarded; arrays,
|
|
544
|
-
strings, ages, booleans, provider records, and external findings are revalidated
|
|
545
|
-
and bounded before scoring. The accepted dataset envelope is:
|
|
546
|
-
|
|
547
|
-
```json
|
|
548
|
-
{
|
|
549
|
-
"schema": "whoisleuth.risk-calibration-dataset",
|
|
550
|
-
"version": 2,
|
|
551
|
-
"records": [
|
|
552
|
-
{
|
|
553
|
-
"id": "fixture-1",
|
|
554
|
-
"domain": "login.example.test",
|
|
555
|
-
"analystDisposition": "confirmed_abuse",
|
|
556
|
-
"reviewReasonCode": "confirmed_credential_abuse",
|
|
557
|
-
"evidence": {
|
|
558
|
-
"availability": "registered",
|
|
559
|
-
"mutationTypes": ["dictionary"],
|
|
560
|
-
"hasPasswordField": true
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
]
|
|
564
|
-
}
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
`confirmed_abuse` is treated as a positive calibration label; `false_positive`
|
|
568
|
-
and `expected` are negative labels. `unreviewed`, `suspicious`, and
|
|
569
|
-
`closed_no_action` remain contextual and are excluded from threshold quality
|
|
570
|
-
metrics, as are records for which Risk is not applicable. Terminal output caps
|
|
571
|
-
its record list at 100 while `--json` retains the complete bounded detailed report,
|
|
572
|
-
factor breakdowns, score bands, confidence intervals, bounded strata, model
|
|
573
|
-
comparison counts, and per-threshold confusion metrics. Analyst
|
|
574
|
-
dispositions and heuristic scores are review context: neither proves
|
|
575
|
-
maliciousness or safety.
|
|
576
|
-
|
|
577
|
-
The authenticated Monitor workspace can deliberately create the accepted
|
|
578
|
-
dataset from explicitly selected cases. Selection is available only when a case
|
|
579
|
-
has a reviewed disposition and retained normalised evidence. That local export
|
|
580
|
-
contains the case ID, domain, disposition, optional reviewed reason code, and a
|
|
581
|
-
bounded whitelist of current scoring inputs. A matched review-language signal
|
|
582
|
-
is exported as a fixed indicator, not as captured page text. It excludes notes,
|
|
583
|
-
tags, assertions, actions, contacts, raw
|
|
584
|
-
source data, provider payloads, and stored Risk scores. Before download, a local
|
|
585
|
-
review step shows the selected, included, and excluded counts, the domains and
|
|
586
|
-
dispositions that will be written, and the excluded evidence classes. The CLI
|
|
587
|
-
still validates every exported record and never trains, tunes, or changes the
|
|
588
|
-
Risk model.
|
|
589
|
-
|
|
590
|
-
## Lookalike review-yield calibration
|
|
591
|
-
|
|
592
|
-
`lookalike-calibrate [dataset.json]` summarises reviewed candidate outcomes by
|
|
593
|
-
mutation family without retaining domains, candidate identifiers, analyst
|
|
594
|
-
notes, or evidence values in its output. Input uses
|
|
595
|
-
`whoisleuth.lookalike-calibration-input` version 1, is capped at 2 MiB and 5,000
|
|
596
|
-
unique opaque records, and requires one reviewed disposition plus from 1 to 12
|
|
597
|
-
bounded mutation-family identifiers per record.
|
|
598
|
-
|
|
599
|
-
The report keeps exact disposition counts, review-lead rate, false-positive
|
|
600
|
-
rate, and a per-family sample state. Fewer than 20 reviewed observations remains
|
|
601
|
-
`insufficient`. The command is diagnostic only: it does not tune candidate
|
|
602
|
-
generation, filtering, ranking, or Risk, and a useful historical yield does not
|
|
603
|
-
establish that a current candidate is malicious or safe.
|
|
604
|
-
|
|
605
|
-
## Offline artefact verification
|
|
606
|
-
|
|
607
|
-
`verify-artifact` validates a supported local artefact without printing its
|
|
608
|
-
evidence contents. Input is capped at 15 MiB. It currently recognises ordinary
|
|
609
|
-
and encrypted workspace archives, case-response packets, acquisition-decision
|
|
610
|
-
exports, supported Lookup-evidence exports, Lookup claim passports, domain-comparison exports, Bulk mail-exposure exports, and Bulk review
|
|
611
|
-
manifests. Reviewed CLI case packs are checked against their canonical digest,
|
|
612
|
-
bounded browser-importable case collection, audience, and review marker. The
|
|
613
|
-
command verifies both the embedded projections and whole-capsule digest of an
|
|
614
|
-
investigation capsule version 2, including its metadata and linked
|
|
615
|
-
source-contract digests, and reports `verified`. The non-embedded Lookup
|
|
616
|
-
evidence must still be retained separately. Legacy capsule version 1 covers
|
|
617
|
-
only the embedded brief, graph, and optional analyst-record projections, so it
|
|
618
|
-
remains `integrity_valid` rather than whole-file `verified`. It also validates
|
|
619
|
-
the bounded versioned structure of saved CLI Lookup JSON and current
|
|
620
|
-
Lookup-evidence schemas 25 and 26. Because neither saved Lookup documents nor full
|
|
621
|
-
Lookup-evidence exports embed a checksum or signature, those results are
|
|
622
|
-
reported as `structure_valid` with content integrity explicitly unchecked.
|
|
623
|
-
Lookup-evidence verification closes the supported export envelopes and source
|
|
624
|
-
wrappers, enforces the same 5 MiB, 20,000-entry, and 24-level limits as browser
|
|
625
|
-
replay, and does not claim that
|
|
626
|
-
an observation is accurate, current, or unchanged. Exact retained-file identity
|
|
627
|
-
requires a verified investigation manifest and matching `--manifest-entry`;
|
|
628
|
-
the evidence file can contain a bounded privacy-projected registry RDAP
|
|
629
|
-
publication, normalised WHOIS values, and bounded contacts, so review it before
|
|
630
|
-
sharing. Request and response headers, cookies, session and credential fields,
|
|
631
|
-
and URL credentials, queries, and fragments are excluded. Saved Lookup validation retains its
|
|
632
|
-
stricter 8 MiB document ceiling.
|
|
633
|
-
|
|
634
|
-
For an ordinary workspace archive, the command validates the versioned
|
|
635
|
-
structure, section byte counts, record counts, and per-section checksums. For a
|
|
636
|
-
supported signed review artefact, it validates the declared SHA-256 digest. An
|
|
637
|
-
encrypted archive without `--passphrase-file` can establish only that the
|
|
638
|
-
envelope is structurally valid; it reports `envelope_valid` and explicitly
|
|
639
|
-
leaves authenticated encryption and inner checksums unchecked.
|
|
640
|
-
Checksum validity is reported separately from importability. A checksum-valid
|
|
641
|
-
archive can therefore list unsupported sections when it contains a section
|
|
642
|
-
schema this version cannot restore, or skipped and pruned records when a
|
|
643
|
-
supported section cannot be restored completely; inspect those counts before
|
|
644
|
-
importing.
|
|
645
|
-
|
|
646
|
-
Supplying a separate passphrase file, capped at 1 KiB, allows authenticated
|
|
647
|
-
decryption followed by the ordinary workspace checks. The passphrase is never
|
|
648
|
-
accepted as a command-line value, printed, or retained. Verification detects
|
|
649
|
-
changes against the artefact's declared contract; it does not authenticate the
|
|
650
|
-
analyst or establish that an observation was accurate or remains current.
|
|
651
|
-
|
|
652
|
-
`--manifest <manifest.json> --manifest-entry <artifact-N>` additionally verifies
|
|
653
|
-
the selected investigation manifest before comparing its declared entry with
|
|
654
|
-
the supplied artefact. `identity_verified` requires the exact UTF-8 byte length
|
|
655
|
-
and raw digest as well as canonical digest, schema, and version. A
|
|
656
|
-
`canonical_match_only` result means semantic JSON identity survived but the
|
|
657
|
-
retained bytes differ, so it is a partial result under `--strict-exit`.
|
|
658
|
-
`mismatch` likewise remains separate from the artefact's own structure or
|
|
659
|
-
integrity result. Manifest paths and artefact contents are not copied into the
|
|
660
|
-
verification report.
|
|
661
|
-
|
|
662
|
-
Verification reports use `whoisleuth.offline-artifact-verification` version 3
|
|
663
|
-
and do not expose an always-true validity shortcut. The explicit state and
|
|
664
|
-
checks distinguish structure, whole-file integrity, projection integrity, and
|
|
665
|
-
authenticated encryption. `--strict-exit` returns exit 0 for `verified` and
|
|
666
|
-
`structure_valid` when no manifest identity is requested or exact identity is
|
|
667
|
-
verified. It returns partial-failure exit 4 for `integrity_valid`,
|
|
668
|
-
`envelope_valid`, canonical-only identity, or identity mismatch; ordinary
|
|
669
|
-
verification errors retain their existing error codes. Raw JSON is scanned
|
|
670
|
-
before parsing to reject duplicate object keys and excessive nesting or
|
|
671
|
-
key/value counts.
|
|
672
|
-
|
|
673
|
-
Current integrity-bearing review outputs use `sorted-json-v2`, whose object-key
|
|
674
|
-
order is a locale-independent JavaScript code-unit order. Readers select the
|
|
675
|
-
canonical bytes from an exact artifact-version and canonicalization pair,
|
|
676
|
-
reject mixed or missing current declarations, and validate bounded structure
|
|
677
|
-
before any legacy hashing. Historical outputs keep their original
|
|
678
|
-
`sorted-json-v1` bytes and are accepted only through their legacy version.
|
|
679
|
-
Version 1 used the runtime's ambient `localeCompare` ordering, so historical
|
|
680
|
-
files containing non-ASCII object-key extensions require a compatible locale
|
|
681
|
-
and ICU ordering to verify; it is not a portable canonicalization guarantee.
|
|
682
|
-
The fixed keys emitted by the supported legacy builders are ASCII, but only
|
|
683
|
-
version 2 provides the cross-locale portability contract.
|
|
684
|
-
|
|
685
|
-
The current/legacy integrity pairs are: acquisition decision 2/1, Lookup claim
|
|
686
|
-
passport 1 (sorted-json-v2 only),
|
|
687
|
-
domain-comparison export 4/3 with nested comparison 3, Bulk mail-exposure
|
|
688
|
-
export 2/1 with nested report 1, Bulk review manifest 2/1, domain-control
|
|
689
|
-
manifest 2/1, domain-change packet 2/1 with input 1, investigation manifest
|
|
690
|
-
2/1, case-response packet 6/5, investigation capsule 2/1, CLI case-pack packet
|
|
691
|
-
2/1 with Case schema 12, and signed evidence package 2/1. Current outputs
|
|
692
|
-
declare `sorted-json-v2`; legacy declarations remain explicit only where their
|
|
693
|
-
historical contract included one.
|
|
694
|
-
|
|
695
|
-
## Interchange fidelity report
|
|
696
|
-
|
|
697
|
-
`interchange-report [artifact.json]` explains what one recognised portable
|
|
698
|
-
artefact preserves, excludes, and supports in browser and CLI workflows. It
|
|
699
|
-
recognises supported Lookup-evidence exports, Lookup claim passports, domain-control passports, Brand Profile exports from versions 2
|
|
700
|
-
through 6, workspace archives from versions 1 through 5, encrypted workspace
|
|
701
|
-
envelopes, reviewed CLI case packs, and the retired one-way desired-baseline
|
|
702
|
-
export. The retired export is identified as unsupported rather than silently
|
|
703
|
-
treated as a current passport.
|
|
704
|
-
|
|
705
|
-
Output is metadata-only: registered schema and version, verification state,
|
|
706
|
-
bounded counts, browser import/export support, CLI read/write/verify support,
|
|
707
|
-
semantic fidelity, and fixed preserved or excluded field-group identifiers.
|
|
708
|
-
For workspace archives, checksum validity and complete browser importability are
|
|
709
|
-
reported separately. A checksum-valid archive with a newer inner section stays
|
|
710
|
-
verified for integrity while its fidelity is withheld and importability is
|
|
711
|
-
reported as partial. The same partial state applies when browser preview would
|
|
712
|
-
block a section, skip a malformed record, or prune data to a collection bound.
|
|
713
|
-
It never echoes a target, contact, note, evidence value, passphrase, arbitrary
|
|
714
|
-
unknown schema string, or encrypted content. A separate `--passphrase-file`
|
|
715
|
-
can authenticate an encrypted workspace; without it, only the envelope is
|
|
716
|
-
reported as valid and fidelity is withheld. Each registered interchange family
|
|
717
|
-
declares its exact assurance requirement: browser-importable structure is
|
|
718
|
-
sufficient for Brand Profile normalisation and the current bounded
|
|
719
|
-
Lookup-evidence contract, while checksummed formats
|
|
720
|
-
require whole-file integrity and encrypted workspaces additionally require
|
|
721
|
-
authenticated decryption. “Semantic exact after normalisation” does not mean byte
|
|
722
|
-
identity, current evidence, or a successful round trip through an unrelated
|
|
723
|
-
format.
|
|
724
|
-
|
|
725
|
-
For case packs, the fixed fidelity metadata explicitly lists public-audience
|
|
726
|
-
Brand Profile references as excluded and trusted/internal references as
|
|
727
|
-
preserved. The report never prints an identifier or other stored value.
|
|
728
|
-
|
|
729
|
-
## Privacy-safe source reliability report
|
|
730
|
-
|
|
731
|
-
`source-report` summarises source states, durations, truncation, and rate-limit
|
|
732
|
-
counts from one version-1 CLI Lookup, Bulk, or Bulk-item document, a JSON array
|
|
733
|
-
of up to 100 such documents, or an array containing only previously generated
|
|
734
|
-
source-reliability reports. Lookup documents and reports cannot be mixed.
|
|
735
|
-
Merged reports preserve exact state and sample totals and add bounded ranges
|
|
736
|
-
for each input report's median and p95 duration, a bounded source timeline,
|
|
737
|
-
fast/deep/unknown cohorts, and the earliest and latest valid report generation
|
|
738
|
-
times. Exact duplicate reports are rejected so one saved report is not
|
|
739
|
-
accidentally counted twice. Per-source failure, partial, truncation, and
|
|
740
|
-
rate-limit rates remain separate. The command does not pretend that aggregate
|
|
741
|
-
timing distributions can reconstruct the original target-level samples. Input
|
|
742
|
-
is capped at 12 MiB and traversal, source, duration, and output counts are
|
|
743
|
-
bounded.
|
|
744
|
-
|
|
745
|
-
The report retains only fixed source identifiers and aggregate operational
|
|
746
|
-
counts. It does not output targets, queries, endpoints, source limitations, raw
|
|
747
|
-
evidence, or provider payloads. Observation-envelope duration and the
|
|
748
|
-
potentially overlapping Lookup timing are reported separately and never added
|
|
749
|
-
together. It is a local engineering diagnostic, not analytics, a source-quality
|
|
750
|
-
score, or evidence that a collector is currently healthy.
|
|
751
|
-
|
|
752
|
-
## Workspace archive inspection
|
|
753
|
-
|
|
754
|
-
`inspect-archive` verifies an ordinary or encrypted workspace archive and then
|
|
755
|
-
reports its versioned sections, counts, byte sizes, and checksum states without
|
|
756
|
-
printing stored records. An encrypted archive requires
|
|
757
|
-
`--passphrase-file`; passphrases are never accepted on the command line.
|
|
758
|
-
|
|
759
|
-
An optional `--search` is exact and case-insensitive across a fixed allowlist
|
|
760
|
-
of target fields. Default matches disclose only the section, field name, and a
|
|
761
|
-
SHA-256 digest. `--reveal` must be selected explicitly to print the matched
|
|
762
|
-
value. Notes, contacts, raw evidence, arbitrary object fields, and partial text
|
|
763
|
-
search are excluded. Unicode domain searches are canonicalized to their
|
|
764
|
-
DNS-safe ASCII form before exact comparison. `--require-match` makes a
|
|
765
|
-
no-match result fail for automation and is valid only with `--search`.
|
|
766
|
-
Traversal, input size, matches, depth, arrays, and strings are bounded.
|
|
767
|
-
|
|
768
|
-
Version 2 of the inspection report adds a content digest over the ordered
|
|
769
|
-
section identifiers, schema versions, record counts, and normalised section
|
|
770
|
-
content. It deliberately excludes JSON formatting and each section envelope's
|
|
771
|
-
export time, so two separately exported archives with the same retained
|
|
772
|
-
workspace content have the same identity. `--expect-content-digest <sha256:digest>`
|
|
773
|
-
fails when that identity differs, which supports deliberate transfer checks
|
|
774
|
-
without printing records. Matching digests detect equivalent retained content;
|
|
775
|
-
they do not authenticate who created it or establish that its evidence is
|
|
776
|
-
accurate or current. The report separately identifies the source archive
|
|
777
|
-
version and the installed reader version.
|
|
778
|
-
|
|
779
|
-
## Optional evidence-package signing
|
|
780
|
-
|
|
781
|
-
`sign-artifact` signs a locally verified case-response packet or supported
|
|
782
|
-
review manifest with an externally managed Ed25519 private key:
|
|
783
|
-
|
|
784
|
-
```bash
|
|
785
|
-
node bin/whoisleuth.mts sign-artifact packet.json --private-key-file analyst-private.pem > packet.signed.json
|
|
786
|
-
node bin/whoisleuth.mts verify-signature packet.signed.json --public-key-file analyst-public.pem
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
New signed packages use version 2 with `sorted-json-v2` canonicalisation and
|
|
790
|
-
embed the public key, key identifier, canonical UTC signature time, and
|
|
791
|
-
original artefact. Signing requires verified structure plus a verified
|
|
792
|
-
applicable integrity contract; a recomputed digest around an empty or malformed
|
|
793
|
-
document is rejected. Signature verification reports cryptographic status and
|
|
794
|
-
embedded-artifact assurance separately in
|
|
795
|
-
`whoisleuth.evidence-signature-verification` version 2. A result can therefore
|
|
796
|
-
remain `signature_valid` while embedded-artifact assurance is `not_verified`;
|
|
797
|
-
the signature authenticates those exact bytes without upgrading their
|
|
798
|
-
structure or inner integrity. Signer trust is separately reported as
|
|
799
|
-
`trusted_key` or `embedded_key_only`. Without a separately supplied trusted public key,
|
|
800
|
-
verification establishes only that the package is internally self-consistent.
|
|
801
|
-
Historical version-1 packages remain verifiable with their explicit
|
|
802
|
-
`sorted-json-v1` signature declaration when their original locale-dependent
|
|
803
|
-
ordering is reproduced; version 2 is the portable signature contract.
|
|
804
|
-
WHOISleuth does not generate, store, recover, rotate, publish, or establish
|
|
805
|
-
trust in signing keys.
|
|
806
|
-
|
|
807
|
-
## Reproducible investigation manifest
|
|
808
|
-
|
|
809
|
-
`manifest <artefact.json> [...] --workflow <label>` reads from 1 to 16 ordered
|
|
810
|
-
JSON artefacts and emits `whoisleuth.investigation-manifest` version 2. Each
|
|
811
|
-
entry records its sequence, bounded schema and version metadata, exact UTF-8
|
|
812
|
-
content digest, `sorted-json-v2` canonical JSON digest, and byte count. Version
|
|
813
|
-
1 manifests remain verifiable with their historical digest bytes. The manifest
|
|
814
|
-
also records the installed CLI version and can include an externally calculated
|
|
815
|
-
`--configuration-digest sha256:...` without copying configuration values.
|
|
816
|
-
|
|
817
|
-
Source paths, filenames, command-line arguments, and artefact contents are not
|
|
818
|
-
retained. Individual artefacts are capped at 15 MiB and the ordered set at
|
|
819
|
-
32 MiB. The manifest carries its own canonical integrity digest, works with
|
|
820
|
-
`verify-artifact`, and can be passed to `sign-artifact`. Reproduction still
|
|
821
|
-
requires the exact digested artefacts, compatible source services, and any
|
|
822
|
-
separately held configuration; matching digests do not establish observation
|
|
823
|
-
accuracy or freshness.
|
|
824
|
-
|
|
825
|
-
## Bulk lookup
|
|
826
|
-
|
|
827
|
-
`bulk` accepts a newline-delimited file or stdin. It preserves input order,
|
|
828
|
-
removes case-insensitive duplicates, and returns a result for every retained
|
|
829
|
-
query. Input is capped at 1 MiB. Fast mode is capped at 500 queries with four
|
|
830
|
-
workers by default. Deep mode is capped at 50 queries with two workers by
|
|
831
|
-
default. Explicit concurrency cannot exceed eight in fast mode or three in
|
|
832
|
-
deep mode.
|
|
833
|
-
|
|
834
|
-
Bulk uses the shared compact lookup response, so it does not retain raw RDAP
|
|
835
|
-
objects or WHOIS response bodies. `--json` returns one bounded collection;
|
|
836
|
-
`--jsonl` emits one self-contained versioned item per line. `--domains` emits
|
|
837
|
-
only successfully normalised domain names, while `--queries` preserves the
|
|
838
|
-
selected bounded input queries and is suitable for an exact retry queue.
|
|
839
|
-
Version 2 adds a
|
|
840
|
-
bounded `dnsSummary` projection for observed A, AAAA, NS, and MX records plus
|
|
841
|
-
null MX, SPF, and DMARC state. `--csv` writes fixed columns for automation,
|
|
842
|
-
including the DNS summaries and explicit outcome.
|
|
843
|
-
|
|
844
|
-
`--registered-only`, `--inconclusive-only`, and `--errors-only` are mutually
|
|
845
|
-
exclusive output filters. The first retains registered, for-sale, and expiring
|
|
846
|
-
authority-aware states. The second retains unknown authority states and failed
|
|
847
|
-
rows. The third retains only rows whose lookup operation failed, which is useful
|
|
848
|
-
for producing an exact retry queue without treating an inconclusive successful
|
|
849
|
-
lookup as an operational error. Filtering does not change collection and never
|
|
850
|
-
converts an unavailable or failed source into an unregistered result. Machine
|
|
851
|
-
documents record collected and emitted counts. A mixture of successful and
|
|
852
|
-
failed queries exits with code 4 while preserving every collected result before
|
|
853
|
-
output filtering. For example, `bulk domains.txt --queries --errors-only`
|
|
854
|
-
produces only the exact failed inputs while retaining the partial-failure exit.
|
|
855
|
-
|
|
856
|
-
## Certificate Transparency search
|
|
857
|
-
|
|
858
|
-
`ct-search` accepts one keyword as an argument or on stdin and calls the same
|
|
859
|
-
bounded Certificate Transparency module as the web application. It contacts
|
|
860
|
-
the upstream public log search service directly from the local machine; it
|
|
861
|
-
does not call the hosted WHOISleuth deployment. Quote a multi-word keyword so
|
|
862
|
-
the shell passes it as one argument.
|
|
863
|
-
|
|
864
|
-
Terminal output summarises certificate rows, observed hostnames, canonical
|
|
865
|
-
registrable-domain matches, observation times, bounded certificate-issuance
|
|
866
|
-
groups, and completeness. An issuance group contains names observed together
|
|
867
|
-
in one public certificate record; a cross-domain group is a review lead, not
|
|
868
|
-
an attribution or ownership finding. Terminal output shows at most 100 matches
|
|
869
|
-
and five hostnames per match, with explicit omission notes. `--json` returns
|
|
870
|
-
the complete bounded structured result in the versioned
|
|
871
|
-
`whoisleuth.cli.ct-search` schema. The certificate-group cap is reported
|
|
872
|
-
separately from the registrable-domain result cap. CT observations do not prove
|
|
873
|
-
that a website is active or malicious.
|
|
874
|
-
|
|
875
|
-
## Local certificate event intake
|
|
876
|
-
|
|
877
|
-
`ct-intake [events.json]` reads `whoisleuth.ct-event-batch` version 1 entirely
|
|
878
|
-
offline. Each source-qualified event supplies a log identifier, observation
|
|
879
|
-
time, certificate SHA-256 digest, one or more DNS names, completeness, and
|
|
880
|
-
optional issuer, expiry, and limitations. Unknown fields, malformed names,
|
|
881
|
-
unsupported completeness values, and oversized batches are rejected.
|
|
882
|
-
|
|
883
|
-
JSON output uses the existing `whoisleuth.external-findings` version 4 contract
|
|
884
|
-
and can be deliberately imported into the browser Console. Wildcard names are
|
|
885
|
-
normalised to their base DNS name, exact event/domain duplicates are removed,
|
|
886
|
-
and deterministic output is capped at 100 findings, 25 domains, and 20 findings
|
|
887
|
-
per domain to match the browser import boundary. Omission is stated in each
|
|
888
|
-
retained finding when the supplied batch exceeds those limits. The command
|
|
889
|
-
makes a deterministic event identifier and preserves the supplied log id,
|
|
890
|
-
certificate digest, issuer, expiry, original DNS-name count, and whether the
|
|
891
|
-
bounded import retained the complete supplied name set. This metadata lets the
|
|
892
|
-
browser replay reviewed issuer and certificate-name expectations without
|
|
893
|
-
mistaking an omitted name for a mismatch. The command
|
|
894
|
-
makes no request and treats every certificate event as a review lead, not proof
|
|
895
|
-
that the certificate was served, requested, or controlled by the named domain.
|
|
896
|
-
|
|
897
|
-
## Declarative observation interchange
|
|
898
|
-
|
|
899
|
-
`map-observations [mapping.json]` reads
|
|
900
|
-
`whoisleuth.external-observation-mapping` version 1 and applies one strict,
|
|
901
|
-
declarative profile to at most 500 local records. The profile selects bounded
|
|
902
|
-
dotted field paths for the domain, summary, observation time, optional
|
|
903
|
-
reference, and optional completeness. It fixes one source, evidence class, and
|
|
904
|
-
finding category for the batch. Profiles cannot contain scripts, templates,
|
|
905
|
-
computed expressions, network endpoints, or executable callbacks. Prototype
|
|
906
|
-
paths and unknown fields are rejected.
|
|
907
|
-
|
|
908
|
-
The resulting JSON is the existing browser-compatible
|
|
909
|
-
`whoisleuth.external-findings` version 4 contract. It retains source identity,
|
|
910
|
-
observation time, completeness, and limitations, while stating that field
|
|
911
|
-
semantics were not independently verified. Deterministic output is capped at
|
|
912
|
-
100 findings, 25 domains, and 20 findings per domain. The command makes no
|
|
913
|
-
request and never interprets an omitted field as a negative observation.
|
|
914
|
-
|
|
915
|
-
`oam-export [external-findings.json]` projects that strict findings document
|
|
916
|
-
into `whoisleuth.open-asset-model-bridge` version 1. It uses the documented
|
|
917
|
-
[OWASP Open Asset Model](https://github.com/owasp-amass/open-asset-model)
|
|
918
|
-
vocabulary for bounded `FQDN`, `IPAddress`, and `TLSCertificate` assets plus
|
|
919
|
-
`dns_record` and `san_dns_name` relations. Only typed A, AAAA, and SHA-256
|
|
920
|
-
certificate observations create infrastructure assets or relations. Other
|
|
921
|
-
findings remain represented by their FQDN asset.
|
|
922
|
-
|
|
923
|
-
This bridge wrapper is not a claim that every receiving implementation accepts
|
|
924
|
-
one universal native serialisation. Receivers must validate the projection
|
|
925
|
-
against their supported model version. WHOISleuth preserves source and
|
|
926
|
-
completeness as discovery metadata, does not invent a confidence score, and
|
|
927
|
-
does not treat an edge as proof of ownership, control, coordination, intent,
|
|
928
|
-
safety, or maliciousness.
|
|
929
|
-
|
|
930
|
-
## Lookalike discovery
|
|
931
|
-
|
|
932
|
-
`discover` runs the same pure, bounded lookalike generator as the Discover
|
|
933
|
-
tool without making network requests. It accepts a brand label or a
|
|
934
|
-
domain with one suffix label. The default TLD set is `com,net,org`; replace it
|
|
935
|
-
with `--tlds com,net` when narrower coverage is wanted.
|
|
936
|
-
|
|
937
|
-
Generation presets are `common`, `impersonation`, and `all` (the default).
|
|
938
|
-
Keyboard-aware mutations support `qwerty` (the default), `azerty`, and
|
|
939
|
-
`qwertz`; `--keyboard all` uses their bounded combined neighbour set, including
|
|
940
|
-
adjacent number-row keys. Supply a UTF-8 text file with
|
|
941
|
-
`--dictionary terms.txt` to add up to 100 local terms when
|
|
942
|
-
using the `impersonation` or `all` preset. Dictionary input is capped at 4,096
|
|
943
|
-
bytes and individual terms at 32 characters. Machine output records accepted
|
|
944
|
-
and rejected term counts but never copies the private terms into its metadata.
|
|
945
|
-
|
|
946
|
-
Use `--families <ids>` instead of `--preset` to run an exact comma-separated
|
|
947
|
-
selection. Supported IDs are `character_addition`, `character_omission`,
|
|
948
|
-
`character_duplication`, `character_transposition`, `pluralization`,
|
|
949
|
-
`tld_embedding`, `www_prefix`, `hyphenation`, `separator_omission`,
|
|
950
|
-
`word_reordering`, `keyboard_substitution`, `keyboard_insertion`, `vowel_swap`,
|
|
951
|
-
`bitsquatting`, `ascii_homoglyph`, `unicode_homoglyph`,
|
|
952
|
-
`unicode_whole_label`, `unicode_homoglyph_depth_2`, `dictionary`,
|
|
953
|
-
`dictionary_token_replacement`, `tld_typo`, and `tld_substitution`. Machine
|
|
954
|
-
output records the normalised custom selection. A custom dictionary file
|
|
955
|
-
requires `dictionary` or `dictionary_token_replacement` in that selection.
|
|
956
|
-
|
|
957
|
-
`--domains` writes the unique candidate names only. `--snapshot <file>` keeps
|
|
958
|
-
one private, versioned local observation of the normalised seed, generation
|
|
959
|
-
configuration, custom-dictionary digest, and candidate set. The first run
|
|
960
|
-
creates the snapshot; later runs report added and removed candidates before
|
|
961
|
-
atomically replacing it. The snapshot never stores private dictionary terms.
|
|
962
|
-
Use the same command from a local scheduler such as cron or a system timer to
|
|
963
|
-
perform repeatable discovery runs. WHOISleuth does not install a scheduler,
|
|
964
|
-
run a background daemon, or infer that an added candidate is registered,
|
|
965
|
-
active, available, or malicious.
|
|
966
|
-
|
|
967
|
-
Dotted subdomain permutations are intentionally excluded because the lookup
|
|
968
|
-
pipeline validates a hostname's registrable parent. The CLI does not present
|
|
969
|
-
authoritative parent registration evidence as proof that a generated hostname
|
|
970
|
-
exists.
|
|
971
|
-
|
|
972
|
-
Terminal output is capped at 200 candidates with an explicit notice. Versioned
|
|
973
|
-
JSON and JSONL use `whoisleuth.cli.discover` schema version 2 and retain the
|
|
974
|
-
complete bounded candidate set and mutation provenance. Internationalised
|
|
975
|
-
candidates show the DNS-safe ASCII form and readable Unicode form together in
|
|
976
|
-
terminal output. The Impersonation and All presets can add up to six
|
|
977
|
-
deterministic whole-label Unicode candidates when every letter has a reviewed
|
|
978
|
-
same-script replacement. The command generates candidates only. It does not
|
|
979
|
-
claim that a domain is registered, active, or malicious.
|
|
980
|
-
|
|
981
|
-
`unicode_homoglyph_depth_2` is an explicit `--families` option and is never
|
|
982
|
-
enabled by a preset. It replaces exactly two ASCII letters with characters
|
|
983
|
-
from the same reviewed script, ranks curated mappings first, and returns at
|
|
984
|
-
most 256 candidates. JSON and terminal output report generated candidates,
|
|
985
|
-
cross-script or invalid combinations omitted by policy, and lower-ranked
|
|
986
|
-
label variants omitted by the family or overall generation budget.
|
|
987
|
-
|
|
988
|
-
## Supervised candidate scan
|
|
989
|
-
|
|
990
|
-
`discover-scan` composes the same bounded generator with the compact Lookup
|
|
991
|
-
collector. Unlike `discover`, it is an explicitly networked command. It selects
|
|
992
|
-
the first deterministic candidates up to `--scan-limit`, processes fixed
|
|
993
|
-
chunks sequentially, and retains each registration and DNS source state. Fast
|
|
994
|
-
mode is the default and accepts at most 500 candidates. Explicit `--deep` mode
|
|
995
|
-
is capped at 50 candidates and concurrency 3 because it can add WHOIS, DNS,
|
|
996
|
-
HTTP, TLS, page, and technology work for every selected candidate.
|
|
997
|
-
|
|
998
|
-
Use `--chunk-size 1-100`, `--concurrency 1-8`, and the existing private
|
|
999
|
-
`--checkpoint <file> [--resume]` boundary to control a run. The checkpoint is
|
|
1000
|
-
tied to the exact ordered candidate set and scan mode. A new generation order,
|
|
1001
|
-
limit, or mode requires another checkpoint. `--resolver` accepts at most three
|
|
1002
|
-
literal IPv4 or IPv6 recursive-resolver addresses and applies them only to DNS
|
|
1003
|
-
observations in this local run. Resolver hostnames and automatic third-party
|
|
1004
|
-
resolver selection are not supported. The selected resolvers can observe the
|
|
1005
|
-
queried candidates and may apply their own logging and retention policies.
|
|
1006
|
-
|
|
1007
|
-
An optional newline-delimited `--allowlist` accepts at most 500 domains and 64
|
|
1008
|
-
KiB. Matching candidates remain in evidence and are labelled `suppressed` in
|
|
1009
|
-
the review queue; the full list and unmatched entries are not copied into
|
|
1010
|
-
output, while each matching scanned candidate necessarily exposes that match.
|
|
1011
|
-
Allowlisting never deletes a result or asserts that it is safe. Output filters
|
|
1012
|
-
select registered, inconclusive, acquisition-review, or
|
|
1013
|
-
suppressed rows without changing whole-run counts or source health. JSON,
|
|
1014
|
-
JSONL, CSV, and domain-list forms retain mutation provenance and explicit
|
|
1015
|
-
review lanes. The queue provides next manual actions, not automatic lookup,
|
|
1016
|
-
acquisition, blocking, submission, or enforcement.
|
|
1017
|
-
|
|
1018
|
-
Deep compact results can group exact shared addresses, nameservers, and mail
|
|
1019
|
-
servers observed across at least two candidates. These bounded relationships
|
|
1020
|
-
are pivot leads only. Common hosting, delivery, registrar, and mail services
|
|
1021
|
-
can produce the same relationship without common ownership or control.
|
|
1022
|
-
|
|
1023
|
-
`--observation-snapshot <file>` keeps a private versioned local projection of
|
|
1024
|
-
registration state, confidence, and bounded A, AAAA, NS, MX, null-MX, SPF, and
|
|
1025
|
-
DMARC summaries for the exact candidate set, mode, and resolver selection.
|
|
1026
|
-
Version 2 records registration and DNS observation times and latest component
|
|
1027
|
-
states separately; version 1 is read and normalised on the next write. A later
|
|
1028
|
-
identical run reports material field changes only for components collected
|
|
1029
|
-
with enough completeness to support the comparison. If registration or DNS is
|
|
1030
|
-
partial or unavailable, the prior usable evidence for that component is
|
|
1031
|
-
preserved and the attempt is reported as unavailable rather than converting
|
|
1032
|
-
missing data into a removal. Raw registry
|
|
1033
|
-
records, contacts, page content, and request details are excluded. Snapshot
|
|
1034
|
-
differences are review prompts, not proof of ownership, control, intent,
|
|
1035
|
-
safety, or maliciousness.
|
|
1036
|
-
|
|
1037
|
-
## Domain posture audit
|
|
1038
|
-
|
|
1039
|
-
`posture` runs the standard-profile form of the owned-domain DNS and
|
|
1040
|
-
email-security audit used by Brand Profiles. It queries registry status and
|
|
1041
|
-
DNSSEC evidence, nameserver delegation, SPF, DMARC, MX, CAA, MTA-STS, TLS-RPT,
|
|
1042
|
-
and BIMI directly from the local machine. Literal SPF include and redirect
|
|
1043
|
-
branches are expanded within fixed depth, policy-query, DNS-term, void-answer,
|
|
1044
|
-
cycle, and time bounds. External DMARC reporting authorisation and external
|
|
1045
|
-
nameserver, mail, SPF, and reporting dependencies are separately reported.
|
|
1046
|
-
The MTA-STS policy request uses the fixed HTTPS policy host and well-known path;
|
|
1047
|
-
HTTP redirects are not followed, as required by RFC 8461, and a redirect leaves
|
|
1048
|
-
that evidence unavailable rather than borrowing a policy body from another URL.
|
|
1049
|
-
Supply up to ten known active and retired DKIM selectors in total with
|
|
1050
|
-
`--selectors selector1,selector2` and `--retired-selectors selector0`;
|
|
1051
|
-
selectors cannot be reliably discovered from DNS, so no-selector output
|
|
1052
|
-
reports DKIM as not checked. Use `--mail-profile standard`,
|
|
1053
|
-
`--mail-profile defensive-no-mail`, or `--mail-profile parked` to make the
|
|
1054
|
-
intended mail posture explicit rather than inferring it from DNS.
|
|
1055
|
-
|
|
1056
|
-
Terminal output shows each pass, review, action, or informational result and
|
|
1057
|
-
caps displayed records at five per check with an explicit omission notice.
|
|
1058
|
-
Versioned JSON retains the complete bounded report, including SPF traversal,
|
|
1059
|
-
DMARC authorisation, and dependency provenance. Warnings and dangers are
|
|
1060
|
-
findings rather than command failures; transient resolver or policy-fetch
|
|
1061
|
-
failures remain informational and should be retried before changing DNS.
|
|
1062
|
-
|
|
1063
|
-
## HTTP intelligence
|
|
1064
|
-
|
|
1065
|
-
`http` runs the same bounded safe homepage probe used by a deep lookup. It
|
|
1066
|
-
tries HTTPS before HTTP, follows only validated public-network redirects, caps
|
|
1067
|
-
each attempt at six seconds, and captures at most 300,000 response bytes for
|
|
1068
|
-
hashing and metadata. A non-success HTTP response still proves that a web
|
|
1069
|
-
service answered; failure of both schemes remains inconclusive rather than
|
|
1070
|
-
evidence that no website exists.
|
|
1071
|
-
|
|
1072
|
-
The command reports normalised redirect, response, content, selected security-
|
|
1073
|
-
header, body-hash, completeness, and attempt provenance. Captured homepage text
|
|
1074
|
-
is never written to terminal or JSON output. Query strings are removed by the
|
|
1075
|
-
shared HTTP evidence normalizer, and terminal values are additionally bounded
|
|
1076
|
-
and control-safe.
|
|
1077
|
-
|
|
1078
|
-
## TLS intelligence
|
|
1079
|
-
|
|
1080
|
-
`tls` runs the same bounded one-connection TLS collector used by deep lookups.
|
|
1081
|
-
It resolves the hostname once through the public-address guard, validates every
|
|
1082
|
-
answer, connects directly to the first validated address on port 443, and keeps
|
|
1083
|
-
the original hostname for SNI and certificate identity checking. Resolution
|
|
1084
|
-
and handshake work share a five-second deadline.
|
|
1085
|
-
|
|
1086
|
-
The report retains the negotiated protocol, ALPN and cipher, runtime trust and
|
|
1087
|
-
hostname checks, certificate validity, bounded subject and issuer names, SANs,
|
|
1088
|
-
SAN class counts, signature algorithm and OID, extended-key-usage purposes,
|
|
1089
|
-
classified Authority Information Access presence counts, SHA-256 certificate
|
|
1090
|
-
and public-key fingerprints, a bounded certificate chain, and neutral
|
|
1091
|
-
findings. AIA responder and issuer locations are classified as HTTP, HTTPS, or
|
|
1092
|
-
other and then discarded; they are not retained or followed. The collector
|
|
1093
|
-
stores no certificate bytes, session material, or application data and does
|
|
1094
|
-
not enumerate supported protocol or cipher suites.
|
|
1095
|
-
A failed collection is inconclusive rather than proof that no TLS service
|
|
1096
|
-
exists.
|
|
1097
|
-
|
|
1098
|
-
## Registry-source comparison
|
|
1099
|
-
|
|
1100
|
-
`compare` reads one version-1 `whoisleuth.cli.lookup` domain document from a
|
|
1101
|
-
file or stdin and emits a version-3 `whoisleuth.cli.compare` document. Its
|
|
1102
|
-
primary comparison reconciles normalised registry RDAP and WHOIS fields. When
|
|
1103
|
-
the saved deep lookup also represents the optional registrar RDAP follow-up,
|
|
1104
|
-
an additional sibling comparison reconciles the portable registry and
|
|
1105
|
-
registrar RDAP publication fields. The command does not repeat the lookup,
|
|
1106
|
-
contact the hosted deployment, or treat a conflict as a command failure. Use a
|
|
1107
|
-
deep lookup when multiple sources are wanted; a fast lookup deliberately
|
|
1108
|
-
records WHOIS as skipped, and comparison preserves that state as unavailable
|
|
1109
|
-
rather than misreporting RDAP-only publication.
|
|
1110
|
-
|
|
1111
|
-
Input is capped at 8 MiB and must retain the lookup schema, mode, source
|
|
1112
|
-
diagnostics, and normalised parsed source sections. Per-value, list, and event
|
|
1113
|
-
bounds are revalidated because saved JSON is treated as untrusted input. A
|
|
1114
|
-
successful registrar source must include a normalised object and agree with
|
|
1115
|
-
its diagnostic status. Raw RDAP JSON, registrar contacts and source-specific
|
|
1116
|
-
handles, WHOIS response bodies, availability evidence, and unrelated lookup
|
|
1117
|
-
fields are not copied into the comparison result.
|
|
1118
|
-
|
|
1119
|
-
When the saved Lookup contains valid version-5, version-6, or version-7, context-only
|
|
1120
|
-
registry-access diagnostics, version 3 retains their bounded suffix, access profiles, and
|
|
1121
|
-
limitation. Terminal output labels the same collection context explicitly.
|
|
1122
|
-
It explains source reachability only and cannot decide registration,
|
|
1123
|
-
availability, ownership, safety, or maliciousness. Older documents and saved
|
|
1124
|
-
lookups without that context do not gain a registry-access field.
|
|
1125
|
-
|
|
1126
|
-
Terminal and versioned JSON output cover domain identity, registry object ID,
|
|
1127
|
-
registrar, registrar IANA ID, lifecycle dates, DNSSEC, statuses, and name
|
|
1128
|
-
servers. The shared comparison model normalises harmless case, punctuation,
|
|
1129
|
-
ordering, and date-precision differences while distinguishing conflicts,
|
|
1130
|
-
one-source publication, redaction, incomplete sources, and unavailable
|
|
1131
|
-
sources. This is source reconciliation, not an availability, ownership, or
|
|
1132
|
-
maliciousness decision.
|
|
1133
|
-
|
|
1134
|
-
## Static page comparison
|
|
1135
|
-
|
|
1136
|
-
`page-compare <left.json> <right.json>` reads two different version-1 saved
|
|
1137
|
-
Deep domain Lookup documents and compares the already-retained static page
|
|
1138
|
-
identity, exact and perceptual favicon evidence, technology identifiers, TLS
|
|
1139
|
-
issuer label, and TLS public-key fingerprint. DOM structure is compared first
|
|
1140
|
-
by its exact bounded tag-sequence digest, then, when both captures provide it,
|
|
1141
|
-
by a parse5-tokenized structural SimHash. It makes no request and requires
|
|
1142
|
-
complete supported static page-identity observations on both sides.
|
|
1143
|
-
|
|
1144
|
-
Each page component remains independent. Exact, similar, overlapping,
|
|
1145
|
-
different, unavailable, and partial evidence are not collapsed into a score.
|
|
1146
|
-
Version 3 also withholds technology-set equality and disjointness whenever
|
|
1147
|
-
either saved technology observation is partial or truncated; the retained
|
|
1148
|
-
identifiers remain visible only as incomplete evidence.
|
|
1149
|
-
Matching components are investigative relationships rather than proof of
|
|
1150
|
-
copying, common ownership, control, intent, safety, or maliciousness. Static
|
|
1151
|
-
comparison does not execute JavaScript; use the optional local rendered
|
|
1152
|
-
capture package only when that additional active behaviour is authorised.
|
|
1153
|
-
|
|
1154
|
-
## Passive mail exposure review
|
|
1155
|
-
|
|
1156
|
-
`mail-review [bulk.json|bulk.jsonl]` reads version-2 Bulk output locally and
|
|
1157
|
-
summarises MX, null MX, SPF, DMARC, and mail-provider relationships. It keeps
|
|
1158
|
-
authenticated mail, authentication gaps, incomplete authentication evidence,
|
|
1159
|
-
no explicit MX, null MX, and incomplete DNS evidence as separate states.
|
|
1160
|
-
Shared-provider relationships are based only on the registrable domain of an
|
|
1161
|
-
observed MX hostname and do not establish shared ownership or control.
|
|
1162
|
-
|
|
1163
|
-
The command makes no DNS or SMTP request and retains no source path. It does
|
|
1164
|
-
not test message acceptance, relay behaviour, mailbox existence, catch-all
|
|
1165
|
-
behaviour, SMTP banners, or whether a mail server is rogue, safe, or malicious.
|
|
1166
|
-
|
|
1167
|
-
An analyst may add a bounded `tlsaEvidence` object to a version-2 Bulk item for
|
|
1168
|
-
offline DANE review. It must name the exact `_25._tcp.<mx-host>` service, and
|
|
1169
|
-
that host must occur in the same item's retained MX evidence. A certificate
|
|
1170
|
-
association match is complete only when `dnssecState` is `validated`. For an
|
|
1171
|
-
SMTP relay service on `_25._tcp`, PKIX-TA usage 0 and PKIX-EE usage 1 are
|
|
1172
|
-
reported as unsupported and cannot complete SMTP DANE assurance because RFC
|
|
1173
|
-
7672 leaves their SMTP treatment undefined. Usage 2 likewise
|
|
1174
|
-
cannot complete DANE-TA assurance because this offline action does not construct
|
|
1175
|
-
or validate a path from the observed leaf to the supplied trust-anchor material.
|
|
1176
|
-
For other service ports, usage 0 compares against the bounded
|
|
1177
|
-
`authorityMaterials` array and remains path-binding limited, while usage 1
|
|
1178
|
-
compares against the leaf and still requires independently validated PKIX.
|
|
1179
|
-
Usage 3 compares against the supplied leaf certificate or SPKI. Mismatched
|
|
1180
|
-
service names, missing certificate roles, unvalidated prerequisites, malformed
|
|
1181
|
-
material, and truncation remain invalid, partial, or untrusted rather than
|
|
1182
|
-
becoming a DANE match.
|
|
1183
|
-
|
|
1184
|
-
## Isolated cryptographic and mail transport review
|
|
1185
|
-
|
|
1186
|
-
These two network actions are disconnected from Lookup, Bulk, monitoring, and
|
|
1187
|
-
fixed recipes. They run only through their dedicated commands, require
|
|
1188
|
-
`--owned-or-authorized` on every invocation, use one caller-selected literal
|
|
1189
|
-
public resolver address, and require a local version-1
|
|
1190
|
-
`whoisleuth.dnssec-trust-anchor` JSON file. The resolver receives the DNS
|
|
1191
|
-
questions and can apply its own logging and retention. Resolver hostnames,
|
|
1192
|
-
private or reserved addresses, automatic resolver selection, and a non-default
|
|
1193
|
-
DNS port are refused.
|
|
1194
|
-
|
|
1195
|
-
Queries set RD, CD, and EDNS DO so the selected recursive resolver returns
|
|
1196
|
-
DNSSEC material for local validation; the resolver's AD bit is recorded only
|
|
1197
|
-
as response metadata and never substitutes for local cryptographic checks.
|
|
1198
|
-
|
|
1199
|
-
`dnssec-validate <domain> --resolver <public-IP> --trust-anchor <anchor.json>
|
|
1200
|
-
--owned-or-authorized` performs an isolated DNS-over-TCP validation from the
|
|
1201
|
-
supplied anchor. It validates supported DS, DNSKEY, and RRSIG relationships,
|
|
1202
|
-
and supported authenticated NSEC or exact NSEC3 denial evidence. NSEC3 opt-out
|
|
1203
|
-
spans and unknown flags remain explicitly unsupported. The action
|
|
1204
|
-
is capped at 32 DNS queries, eight delegations, 512 KiB of DNS
|
|
1205
|
-
response bytes, 2.5 seconds per query, and 15 seconds total, with no retry.
|
|
1206
|
-
Authenticated RRsets are capped at 32 records and 16 matching signatures, and
|
|
1207
|
-
denial review accepts at most 16 NSEC3 records per response.
|
|
1208
|
-
Canonical RRsets are deduplicated and ordered by canonical RDATA before the
|
|
1209
|
-
fixed owner, type, class, TTL, and length fields are constructed. NSEC Next
|
|
1210
|
-
Domain Name case is preserved as required for its canonical RDATA, while the
|
|
1211
|
-
RRSIG Signer's Name in signed data is canonical lowercase. A positive RRset
|
|
1212
|
-
whose RRSIG label count indicates wildcard expansion remains `unsupported`
|
|
1213
|
-
unless authenticated denial evidence proves the expansion; this version does
|
|
1214
|
-
not infer that proof from the signature alone.
|
|
1215
|
-
Supported signature algorithms are 5, 7, 8, 10, 13, 14, 15, and 16; supported
|
|
1216
|
-
DS digests are 1, 2, and 4; NSEC3 iteration counts above 500 remain
|
|
1217
|
-
unsupported. The output is `whoisleuth.dnssec-chain-validation` version 1 and
|
|
1218
|
-
keeps `secure`, `insecure`, `bogus`, `indeterminate`, `timed_out`,
|
|
1219
|
-
`unsupported`, and `invalid` separate. Resolver transport failures do not
|
|
1220
|
-
become cryptographic failures. The report retains the target, selected
|
|
1221
|
-
resolver, trust-anchor source and review time, validated zones, bounded counts,
|
|
1222
|
-
state, failure stage, and limitations. DNS wire responses, DNSKEY public keys,
|
|
1223
|
-
signatures, and transaction identifiers are not retained. `secure` describes
|
|
1224
|
-
the supported chain at that observation time; it is not an ownership,
|
|
1225
|
-
availability, safety, or maliciousness conclusion.
|
|
1226
|
-
|
|
1227
|
-
The trust-anchor document contains exactly `schema`, `version`, `zone`,
|
|
1228
|
-
`source`, `reviewedAt`, and one to eight `dsRecords`. Each DS entry contains
|
|
1229
|
-
`keyTag`, `algorithm`, `digestType`, and a correctly sized hexadecimal
|
|
1230
|
-
`digest`. The file is capped at 64 KiB. WHOISleuth does not download, refresh,
|
|
1231
|
-
select, or vouch for an anchor; maintaining its source and review time is the
|
|
1232
|
-
operator's responsibility.
|
|
1233
|
-
|
|
1234
|
-
`mail-transport [input.json] --resolver <public-IP> --trust-anchor
|
|
1235
|
-
<anchor.json> --owned-or-authorized --active-probe` additionally requires a
|
|
1236
|
-
separate active-probe acknowledgement on every run. Its version-1
|
|
1237
|
-
`whoisleuth.mail-transport.input` names one domain, one to three distinct
|
|
1238
|
-
selected MX hostnames, and optional bounded `policyContext.mtaSts` and
|
|
1239
|
-
`policyContext.tlsRpt` observations. Policy entries retain a supplied state,
|
|
1240
|
-
source, observation time, and `complete`, `partial`, or `unavailable`
|
|
1241
|
-
completeness; the command does not fetch either policy.
|
|
1242
|
-
|
|
1243
|
-
Selected hosts are processed sequentially. Each host is resolved through the
|
|
1244
|
-
chosen resolver, every returned connection candidate is checked as a public
|
|
1245
|
-
IP address, at most 16 candidates and four aliases are accepted per resolution,
|
|
1246
|
-
and the selected address must still occur in a fresh resolution immediately
|
|
1247
|
-
before one direct pinned port-25 connection. The client accepts only bounded
|
|
1248
|
-
printable-ASCII SMTP reply framing, sends exactly `EHLO whoisleuth.invalid`, and sends
|
|
1249
|
-
`STARTTLS` only when advertised. It never sends `AUTH`, `MAIL FROM`, `RCPT TO`,
|
|
1250
|
-
`DATA`, `VRFY`, `EXPN`, a message, or a retry. Per endpoint, SMTP response data
|
|
1251
|
-
is capped at 16 KiB, 64 lines, 1,000 bytes per line, and 32 retained capability
|
|
1252
|
-
names; one leaf certificate is accepted up to 256 KiB and the fixed endpoint
|
|
1253
|
-
timeout is eight seconds. Expiry aborts and destroys the connection. The entire
|
|
1254
|
-
sequential run is capped at 30 seconds and shares a
|
|
1255
|
-
32-query, 512-KiB DNS budget.
|
|
1256
|
-
|
|
1257
|
-
Address provenance advances only through `selected`, `revalidated`, and
|
|
1258
|
-
`connected`; failures retain the strongest completed stage and never describe a
|
|
1259
|
-
DNS candidate as connection evidence. Successful fresh public-address checking
|
|
1260
|
-
uses `resolution.state=public_revalidated`. The separate
|
|
1261
|
-
`addressAuthentication.state` is `not_evaluated` after an address candidate is
|
|
1262
|
-
retained because the A or AAAA RRset and any CNAME chain are not
|
|
1263
|
-
cryptographically validated by this action; it is `unavailable` when no
|
|
1264
|
-
candidate was retained.
|
|
1265
|
-
|
|
1266
|
-
TLSA records for `_25._tcp.<selected-mx>` are compared only after their RRset
|
|
1267
|
-
or denial evidence validates through that endpoint's separately reported
|
|
1268
|
-
DNSSEC context. PKIX authorisation, certificate hostname identity,
|
|
1269
|
-
DNSSEC-chain validation, TLSA publication, DANE comparison, STARTTLS, SMTP
|
|
1270
|
-
transport, MTA-STS context, and TLS-RPT context retain separate states;
|
|
1271
|
-
missing or incomplete evidence in one family is never filled from another.
|
|
1272
|
-
If a DANE-TA TLSA usage 2 association is published, active STARTTLS review
|
|
1273
|
-
retains only the observed leaf certificate and leaves that comparison partial
|
|
1274
|
-
because this action does not construct or validate a certificate path to a
|
|
1275
|
-
TLSA trust anchor.
|
|
1276
|
-
The `whoisleuth.cli.mail-transport-review` version-1 output retains selected MX
|
|
1277
|
-
names, the bounded address value, family, highest proven address stage, and
|
|
1278
|
-
separate address-authentication state, greeting status and SHA-256 digest, capability
|
|
1279
|
-
names, certificate and SPKI SHA-256 digests, protocol and cipher labels,
|
|
1280
|
-
bounded certificate authorization or identity error text, source times, counts,
|
|
1281
|
-
completeness, and limitations. Raw greeting or reply
|
|
1282
|
-
text, certificate bytes, TLS session material, and DNS wire responses are not
|
|
1283
|
-
retained. Only address values whose stage is `connected` can form an exact
|
|
1284
|
-
shared-address lead. Address, greeting-digest, and certificate-digest matches
|
|
1285
|
-
are labelled review leads only; they do not establish a rogue endpoint, common
|
|
1286
|
-
ownership, coordination, intent, safety, or maliciousness. Neither action
|
|
1287
|
-
changes Risk, Opportunity, registration availability, or any stored browser
|
|
1288
|
-
record.
|
|
1289
|
-
|
|
1290
|
-
## Offline supplied-evidence review
|
|
1291
|
-
|
|
1292
|
-
`review-evidence [evidence.json]` accepts one version-1 JSON input and performs
|
|
1293
|
-
only deterministic local parsing, comparison, or request planning. Input is
|
|
1294
|
-
capped at 16 MiB. The command never retrieves DNS, opens SMTP, contacts an
|
|
1295
|
-
RDAP server, submits a resolver query, or looks up an address in a hosted
|
|
1296
|
-
GeoIP service.
|
|
1297
|
-
|
|
1298
|
-
Supported input schemas are:
|
|
1299
|
-
|
|
1300
|
-
- `whoisleuth.dnssec-evidence-input`: compares bounded DS and DNSKEY records,
|
|
1301
|
-
recalculates DNSKEY key tags and supported DS digests, and reviews supplied
|
|
1302
|
-
RRSIG validity windows at `observedAt`. `consistent` describes only the
|
|
1303
|
-
supplied DS/DNSKEY relationship. It does not authenticate a chain to a root
|
|
1304
|
-
trust anchor, validate RRSIG cryptography, or prove that a missing record is
|
|
1305
|
-
absent.
|
|
1306
|
-
- `whoisleuth.tlsa-evidence-input`: binds TLSA records to one explicit
|
|
1307
|
-
`_port._transport.hostname` service and compares supplied leaf or authority
|
|
1308
|
-
certificate/SPKI bytes. `matched` requires independently validated DNSSEC;
|
|
1309
|
-
PKIX-TA and PKIX-EE usages also require an independently validated PKIX path.
|
|
1310
|
-
PKIX-TA usage 0 retains per-record authority comparisons but cannot complete
|
|
1311
|
-
PKIX-TA assurance because supplied authority material is not proven to belong
|
|
1312
|
-
to that validated path. DANE-TA usage 2 likewise cannot complete DANE-TA
|
|
1313
|
-
assurance because this offline action does not construct or validate a
|
|
1314
|
-
leaf-to-anchor certificate path. The command does not retrieve the certificate
|
|
1315
|
-
or negotiate STARTTLS.
|
|
1316
|
-
- `whoisleuth.rdap-search-input`: normalises a supplied RDAP search-help
|
|
1317
|
-
response and prepares an exact supported reverse-search request without
|
|
1318
|
-
sending it. If the document also contains a previously obtained `response`,
|
|
1319
|
-
the command checks its bounded property mappings against the reviewed
|
|
1320
|
-
registration and reports omitted or unrecognised mappings without treating
|
|
1321
|
-
the response as authoritative or complete.
|
|
1322
|
-
- `whoisleuth.rpki-route-input`: compares a route prefix and origin ASN with a
|
|
1323
|
-
bounded analyst-supplied VRP set.
|
|
1324
|
-
- `whoisleuth.cryptographic-assurance.input`: accepts separately wrapped,
|
|
1325
|
-
source-qualified DNSSEC, route-origin, and DANE/TLSA evidence and emits three
|
|
1326
|
-
independent cards. Every card retains its own authority, source, observation
|
|
1327
|
-
time, state, completeness, result, and limitations. An omitted family remains
|
|
1328
|
-
`unavailable`; the version-1 `whoisleuth.cryptographic-assurance.review`
|
|
1329
|
-
contains `combinedState: null` and never emits a scalar score or combined
|
|
1330
|
-
verdict.
|
|
1331
|
-
- `whoisleuth.local-geoip-query`: queries an analyst-supplied bounded prefix
|
|
1332
|
-
database whose source, version, and licence metadata remain in the result.
|
|
1333
|
-
- `whoisleuth.local-mmdb-query`: with an explicit `--mmdb <database-file>`,
|
|
1334
|
-
queries one analyst-supplied MaxMind DB file locally. The query document must
|
|
1335
|
-
carry `address`, `sourceLabel`, `databaseVersion`, and `license`. WHOISleuth
|
|
1336
|
-
does not bundle, download, update, license, transmit, or retain the database.
|
|
1337
|
-
The nested result uses the same address, network, country, region, city, ASN,
|
|
1338
|
-
source, and limitation fields as the bounded JSON-prefix path. This mode is
|
|
1339
|
-
CLI-only because a hosted or browser deployment cannot open an analyst's
|
|
1340
|
-
local file; its JSON result remains portable to website-compatible evidence
|
|
1341
|
-
archives and reports.
|
|
1342
|
-
- `whoisleuth.encrypted-dns-plan-input`: validates an explicitly reviewed
|
|
1343
|
-
encrypted-DNS provider contract and prepares a bounded query plan. It does
|
|
1344
|
-
not execute the plan.
|
|
1345
|
-
- `whoisleuth.zone-intent.input`: parses either a deliberately supported,
|
|
1346
|
-
bounded BIND master-file subset or normalised DNS records and compares it
|
|
1347
|
-
with one separately attributed observation. TXT values are reduced to
|
|
1348
|
-
SHA-256 digests, unsupported directives and records remain rejected, and an
|
|
1349
|
-
incomplete observation never becomes a missing-record conclusion. The
|
|
1350
|
-
review does not contact a resolver or apply a DNS change.
|
|
1351
|
-
- `whoisleuth.domain-portfolio.input`: reviews up to 500 analyst-supplied
|
|
1352
|
-
domain inventory rows for exact registrar, DNS, mail, certificate and
|
|
1353
|
-
recovery concentration, renewal-review gaps and internal recovery-domain
|
|
1354
|
-
dependencies. Account labels and provider assignments remain analyst
|
|
1355
|
-
assertions, and the review makes no provider or account request.
|
|
1356
|
-
- `whoisleuth.domain-change.input`: compares bounded, separately labelled
|
|
1357
|
-
authority and resolver observations; reviews CDS, CDNSKEY and CSYNC
|
|
1358
|
-
publication consistency; inventories supplied SRV services and ACME
|
|
1359
|
-
dependencies; and records TLS key continuity, stapling, embedded timestamp,
|
|
1360
|
-
and HSTS preload context. TXT values are retained only as SHA-256 digests.
|
|
1361
|
-
The result is an offline review gate, not a DNSSEC validation, preload-list
|
|
1362
|
-
lookup, certificate-authority request, or permission to apply a change.
|
|
1363
|
-
- `whoisleuth.dns-convergence.input`: compares the latest supplied observation
|
|
1364
|
-
from at least two labelled resolvers or network vantages. It preserves
|
|
1365
|
-
converged, divergent, unexpected, incomplete, and insufficient record-set
|
|
1366
|
-
states, can compare against optional expected values, and projects a simple
|
|
1367
|
-
observation-time plus TTL cache horizon. It does not query DNS or decide
|
|
1368
|
-
which divergent value is authoritative, and supplied TTLs do not reveal
|
|
1369
|
-
actual cache age or resolver refresh policy.
|
|
1370
|
-
- `whoisleuth.nameserver-preflight.input`: reviews an intended nameserver set
|
|
1371
|
-
against separately attributed direct-service observations before a
|
|
1372
|
-
delegation change. It checks authoritative service, the served NS set, SOA
|
|
1373
|
-
evidence, public addresses and in-bailiwick glue readiness without querying
|
|
1374
|
-
DNS, opening a socket or changing registry configuration.
|
|
1375
|
-
- `whoisleuth.trust-store-comparison.input`: compares an already-observed,
|
|
1376
|
-
bounded certificate-chain SHA-256 fingerprint set with up to 16
|
|
1377
|
-
analyst-supplied trust-store snapshots. Each snapshot carries its own name,
|
|
1378
|
-
version, source, review time, completeness, and no more than 2,048 anchor
|
|
1379
|
-
fingerprints. Exact intersections, complete non-observations, and
|
|
1380
|
-
inconclusive inputs remain separate. A match does not build or validate a
|
|
1381
|
-
certificate path, and non-observation does not mean a client would reject
|
|
1382
|
-
the chain because served chains commonly omit their root.
|
|
1383
|
-
|
|
1384
|
-
The common output is `whoisleuth.cli.offline-evidence-review` version 1. It
|
|
1385
|
-
retains the nested result's explicit state and limitations. A locally
|
|
1386
|
-
consistent relationship is not converted into a claim about current
|
|
1387
|
-
publication, ownership, safety, or maliciousness.
|
|
1388
|
-
|
|
1389
|
-
`review-evidence --strict-exit` is an opt-in local automation boundary. It
|
|
1390
|
-
returns the partial-failure exit code when an input family exposes an explicit
|
|
1391
|
-
failed `gate`, or when a zone-intent comparison is incomplete or contains a
|
|
1392
|
-
difference, missing value or unexpected value. Other evidence families retain
|
|
1393
|
-
their ordinary exit behaviour; the flag does not invent a pass/fail policy for
|
|
1394
|
-
them. JSON is still emitted before the exit status is selected.
|
|
1395
|
-
|
|
1396
|
-
## Domain control manifests
|
|
1397
|
-
|
|
1398
|
-
`domain-control [input.json]` builds or reviews a bounded desired-state
|
|
1399
|
-
manifest without making a request or changing configuration. A manifest input
|
|
1400
|
-
uses `whoisleuth.domain-control-manifest-input` version 1, includes an expiry,
|
|
1401
|
-
and may record expected nameservers, DS, MX, CAA, TLS issuer, TLS SPKI
|
|
1402
|
-
fingerprint, registrar-lock preference, and a renewal-review date for up to 100
|
|
1403
|
-
domains. Empty fields mean unconfigured; they do not require a record to be
|
|
1404
|
-
absent.
|
|
1405
|
-
|
|
1406
|
-
The emitted `whoisleuth.domain-control-manifest` version 2 is normalised and
|
|
1407
|
-
protected by a `sorted-json-v2` SHA-256 digest. Version 1 remains readable with
|
|
1408
|
-
its historical canonicalization contract. Either version can also be passed to
|
|
1409
|
-
`sign-artifact` for an optional local Ed25519 signature. Integrity and
|
|
1410
|
-
signature verification detect changes and authenticate possession of the
|
|
1411
|
-
selected key; neither establishes that the desired state is correct. Manifest
|
|
1412
|
-
input and verification reject unknown fields, and verification rejects
|
|
1413
|
-
non-canonical content rather than returning a shape that differs from the
|
|
1414
|
-
normalised contract covered by the digest.
|
|
1415
|
-
|
|
1416
|
-
The same version-two manifest is the browser Console's domain-control passport
|
|
1417
|
-
format; its browser and CLI input envelope remains version 1. A deliberately
|
|
1418
|
-
selected passport can move the supported desired-state
|
|
1419
|
-
subset between Brand Profiles and the CLI without copying profile identity,
|
|
1420
|
-
notes, observations, change windows, suppressions, or other browser-only
|
|
1421
|
-
planning. Browser import verifies the digest and presents a field-level,
|
|
1422
|
-
non-destructive preview. A manifest remains an analyst-authored expectation in
|
|
1423
|
-
either runtime; interoperability does not make it observed evidence.
|
|
1424
|
-
|
|
1425
|
-
A review input uses `whoisleuth.domain-control-review-input` version 1 and
|
|
1426
|
-
contains one manifest plus separately attributed observations. Only a complete
|
|
1427
|
-
`observed` field may produce `drift`. Partial, unavailable, unsupported, and
|
|
1428
|
-
missing observations remain inconclusive, and unrelated observations are
|
|
1429
|
-
counted but ignored. The review performs no DNS, RDAP, HTTP, TLS, SMTP, or
|
|
1430
|
-
registrar request.
|
|
1431
|
-
|
|
1432
|
-
The saved-Lookup review envelope uses
|
|
1433
|
-
`whoisleuth.cli.domain-control-review-input` version 1 and accepts from 1 to
|
|
1434
|
-
100 saved Lookup documents. The raw envelope is scanned before parsing for
|
|
1435
|
-
duplicate keys, the prototype-sensitive `__proto__` key, and a 50-level
|
|
1436
|
-
envelope depth that preserves each saved Lookup's standalone 48-level limit.
|
|
1437
|
-
Its aggregate scanner permits up to 5,050,000 keys and 10,100,000 values so
|
|
1438
|
-
the envelope does not silently narrow the per-document version-1 contract;
|
|
1439
|
-
no individual object or array may contain more than 10,000 items, and the
|
|
1440
|
-
command's byte ceiling remains authoritative. Each embedded Lookup is
|
|
1441
|
-
then independently revalidated against its ordinary saved-document bounds.
|
|
1442
|
-
|
|
1443
|
-
## Domain assurance review
|
|
1444
|
-
|
|
1445
|
-
`assurance [input.json]` reviews one bounded analyst-authored workflow entirely
|
|
1446
|
-
offline. Version 1 inputs remain supported. Version 2 adds optional
|
|
1447
|
-
`customChecks` to retirement inputs and remains the current normalised output
|
|
1448
|
-
version. The input uses `whoisleuth.domain-assurance.input` and one of three
|
|
1449
|
-
fixed kinds:
|
|
1450
|
-
|
|
1451
|
-
- `planned-change` records a bounded window, evidence-backed milestones,
|
|
1452
|
-
rollback criteria, and post-change checks;
|
|
1453
|
-
- `recovery-dependencies` reviews up to 100 domains across registrar, DNS,
|
|
1454
|
-
mail, certificate, and recovery providers and highlights exact provider
|
|
1455
|
-
concentration; and
|
|
1456
|
-
- `retirement` checks the fixed decommissioning controls without treating an
|
|
1457
|
-
unchecked item as complete. Version 2 can add up to 20 analyst-defined checks,
|
|
1458
|
-
each with a bounded identifier, label, expected boolean, and true, false, or
|
|
1459
|
-
null observed value.
|
|
1460
|
-
|
|
1461
|
-
Provider labels, readiness confirmations, evidence references, and expected
|
|
1462
|
-
states remain analyst assertions. The output preserves incomplete and
|
|
1463
|
-
needs-review states and gives every negative state an explicit review reason.
|
|
1464
|
-
The versioned input rejects unknown fields and contradictory evidence attached
|
|
1465
|
-
to an unfinished check. It stores no credentials, makes no request, and changes
|
|
1466
|
-
no registrar, DNS, mail, certificate, or recovery configuration.
|
|
1467
|
-
|
|
1468
|
-
## Domain change assurance packet
|
|
1469
|
-
|
|
1470
|
-
`change-packet [input.json]` combines one pre-change domain review, one
|
|
1471
|
-
post-change domain review, and one planned-change assurance input for the same
|
|
1472
|
-
domain. The input remains `whoisleuth.domain-change-packet.input` version 1. The
|
|
1473
|
-
command revalidates each nested contract, summarises changed authoritative
|
|
1474
|
-
record sets, and emits `whoisleuth.domain-change-packet` version 2 with a
|
|
1475
|
-
`sorted-json-v2` SHA-256 integrity digest. Historical packet version 1 remains
|
|
1476
|
-
verifiable with its original digest bytes.
|
|
1477
|
-
|
|
1478
|
-
The packet is ready only when both supplied observation reviews and the change
|
|
1479
|
-
plan pass their own bounded gates. Partial or unavailable evidence remains a
|
|
1480
|
-
review reason. Packet assembly performs no collection or configuration change,
|
|
1481
|
-
and digest validity does not authenticate the analyst. A reviewed packet can be
|
|
1482
|
-
passed to `sign-artifact` when the operator has an independently managed
|
|
1483
|
-
Ed25519 signing-key lifecycle.
|
|
1484
|
-
|
|
1485
|
-
## Pre-sharing review
|
|
1486
|
-
|
|
1487
|
-
`sharing-review [artifact.json]` performs a redacted local preflight before an
|
|
1488
|
-
analyst deliberately shares an artefact. The analyst must select a TLP 2.0
|
|
1489
|
-
marking, a recipient scope, and a bounded purpose. Optional confirmations record
|
|
1490
|
-
human review, personal-data review, and redaction review. The command validates
|
|
1491
|
-
supported artefact integrity where possible, detects stricter embedded TLP
|
|
1492
|
-
markings, and reports only key-category counts plus bounded, control-free schema
|
|
1493
|
-
and integer version metadata. It emits no content values and copies no raw
|
|
1494
|
-
evidence.
|
|
1495
|
-
|
|
1496
|
-
An imported stricter marking cannot be downgraded by the requested marking, and
|
|
1497
|
-
recipient scope is checked against the effective marking. Evading this local
|
|
1498
|
-
preflight remains possible, so the result is a review aid rather than access
|
|
1499
|
-
control, legal advice, or recipient authorisation.
|
|
1500
|
-
|
|
1501
|
-
## Fixed investigation plans
|
|
1502
|
-
|
|
1503
|
-
`workflow-plan <recipe> <domain|brand>` turns one of four fixed recipes into a
|
|
1504
|
-
versioned `whoisleuth.cli.investigation-plan` document. Supported recipes are
|
|
1505
|
-
`domain-triage`, `lookalike-review`, `owned-domain-review`, and
|
|
1506
|
-
`historical-comparison`. Each step names an existing CLI command, carries its
|
|
1507
|
-
arguments as a JSON array, declares whether it is offline or networked, and
|
|
1508
|
-
marks network-disclosure or analyst-selection approval gates.
|
|
1509
|
-
|
|
1510
|
-
The command is plan-only. It does not execute a step, construct a shell script,
|
|
1511
|
-
interpret a placeholder as a file path, read an artefact, make a request,
|
|
1512
|
-
change a case, or submit evidence. Analysts deliberately run selected commands
|
|
1513
|
-
after reviewing their collection boundaries. This provides repeatable
|
|
1514
|
-
domain-specific workflows without an arbitrary automation or plugin surface.
|
|
1515
|
-
|
|
1516
|
-
## Local handoffs and one-shot monitoring
|
|
1517
|
-
|
|
1518
|
-
`brief [lookup.json]` reads one saved Lookup and emits version 2 of the bounded
|
|
1519
|
-
`whoisleuth.cli.lookup-brief` contract. It separates retained facts,
|
|
1520
|
-
contradictions, incomplete source states, and manual actions. Each action
|
|
1521
|
-
states its evidence basis and expected outcome; it does not run the action or
|
|
1522
|
-
create a case.
|
|
1523
|
-
|
|
1524
|
-
`case-pack [cases.json] --audience <internal|trusted|public> --reviewed` reads a
|
|
1525
|
-
browser case export containing at most 25 normalised cases, applies the selected
|
|
1526
|
-
redaction boundary, and emits a browser-importable case collection with a
|
|
1527
|
-
canonical SHA-256 digest and redaction manifest. It refuses an invalid,
|
|
1528
|
-
duplicate, larger, or generated package above the browser's 2 MiB import limit
|
|
1529
|
-
rather than silently omitting records or evidence. Trusted output removes notes,
|
|
1530
|
-
recipient values, and manual-pivot targets. Public output additionally removes
|
|
1531
|
-
actions, analyst assertions, named investigation branches, and every exact
|
|
1532
|
-
Brand Profile identifier from both the top-level cases and embedded Case report
|
|
1533
|
-
v8 projections. Its redaction manifest records the bounded
|
|
1534
|
-
`brandProfileReferencesOmitted` count, which cannot exceed 200. Trusted and
|
|
1535
|
-
internal output preserve the exact references and record zero omissions.
|
|
1536
|
-
Trusted output retains branch references while redacting action recipients.
|
|
1537
|
-
The review flag records an explicit choice; it does not prove recipient
|
|
1538
|
-
authorisation, profile ownership, attribution, or factual correctness.
|
|
1539
|
-
|
|
1540
|
-
`verify-artifact` recognises the complete case-pack envelope before browser
|
|
1541
|
-
import. It checks the canonical digest, supported case-export schema, bounded
|
|
1542
|
-
case count, report count, audience and explicit review marker without printing
|
|
1543
|
-
case contents. For Case schema 12 it validates the opaque-reference syntax,
|
|
1544
|
-
requires public cases and reports to contain no references, and requires
|
|
1545
|
-
trusted or internal report references to match their top-level case. The
|
|
1546
|
-
case-pack envelope is version 2 with `sorted-json-v2` integrity; a valid legacy
|
|
1547
|
-
version-1 pack carrying a
|
|
1548
|
-
pre-v12 Case collection remains accepted without inventing the new field or
|
|
1549
|
-
redaction count. Current builders reject a schema-12 raw case unless its
|
|
1550
|
-
complete bounded Case projection, safe canonical identity, and unique
|
|
1551
|
-
at-most-eight reference list survive normalisation exactly; over-bound notes,
|
|
1552
|
-
actions, and other fields are not silently truncated. Legacy builder input
|
|
1553
|
-
remains lenient for later fields. Before digest calculation, the verifier binds
|
|
1554
|
-
each report's supported schema version, canonical Case identifier, domain, and
|
|
1555
|
-
audience-sensitive projection to its top-level case. It rejects re-signed
|
|
1556
|
-
public notes, actions, assertions, branches, recipients, manual-trail targets,
|
|
1557
|
-
or Brand Profile references, and the corresponding trusted-field leaks,
|
|
1558
|
-
including copies at unexpected nested paths. It also enforces the exact
|
|
1559
|
-
epoch-specific audience exclusion list, source-case count, and omission-count
|
|
1560
|
-
rules. Current Case schema 12 requires report v8, schema 11 requires report v7,
|
|
1561
|
-
and schemas through 10 accept supported reports through v6 without inventing
|
|
1562
|
-
later branch or Brand-reference fields. For every audience and Case schema 2
|
|
1563
|
-
through 11, retained Case and report nodes must have the same object, array,
|
|
1564
|
-
null, or scalar kind as their bounded normalised projection, and every nested
|
|
1565
|
-
key must belong to that versioned projection. Historical omissions remain
|
|
1566
|
-
valid, while re-signed scalar substitutions and undeclared private fields do
|
|
1567
|
-
not. These checks
|
|
1568
|
-
also govern offline verification and interchange-fidelity classification. This
|
|
1569
|
-
detects a changed or internally inconsistent hand-off file but does not
|
|
1570
|
-
authenticate the analyst, recipient, source observations, or review decision.
|
|
1571
|
-
|
|
1572
|
-
`monitor-once [manifest.json]` performs one bounded Deep control review for at
|
|
1573
|
-
most 20 manifest domains with concurrency capped at three. An optional
|
|
1574
|
-
`--previous` checkpoint adds local first/last-observed comparison. It is not a
|
|
1575
|
-
daemon or scheduler, retains compact normalised observations rather than raw
|
|
1576
|
-
payloads, and keeps failed collection incomplete. JSON, JUnit, and explicit
|
|
1577
|
-
failure policies are supported.
|
|
1578
|
-
|
|
1579
|
-
`workflow-run <recipe> <subject>` executes only concrete steps from the four
|
|
1580
|
-
installed fixed recipes. Network steps require `--approve-network` for that
|
|
1581
|
-
invocation. Analyst-selection placeholders always pause. A bounded `--resume`
|
|
1582
|
-
state must match the exact recipe and subject, cannot add commands or shell
|
|
1583
|
-
syntax, and is not evidence that earlier results remain current. Retained
|
|
1584
|
-
successful steps must form an exact contiguous prefix of the installed recipe,
|
|
1585
|
-
including command, ordered arguments, mode and output schema. A final failed
|
|
1586
|
-
step is retried rather than trusted as completed.
|
|
1587
|
-
|
|
1588
|
-
The `domain-triage` plan deliberately pairs `export` with `verify-artifact`.
|
|
1589
|
-
A fresh current Lookup-evidence export must pass the verifier as
|
|
1590
|
-
`structure_valid`; this establishes bounded contract compatibility, not a
|
|
1591
|
-
checksum, signature, source truth, or observation currency.
|
|
1592
|
-
|
|
1593
|
-
## Optional local rendered capture
|
|
1594
|
-
|
|
1595
|
-
`packages/web-capture` is a private repo-local Playwright package, not part of
|
|
1596
|
-
the distributable core CLI or hosted application. It requires an explicit
|
|
1597
|
-
authorisation flag, one domain-hosted HTTP(S) target, and one new output
|
|
1598
|
-
directory. IP-literal targets are rejected so successful manifests remain
|
|
1599
|
-
compatible with the domain-only Cases importer:
|
|
1600
|
-
|
|
1601
|
-
```bash
|
|
1602
|
-
npm run capture:local -- https://example.test --output-dir ./capture-example --authorize-rendered-capture
|
|
1603
|
-
npm run capture:compare -- ./official/manifest.json ./candidate/manifest.json --json
|
|
1604
|
-
```
|
|
1605
|
-
|
|
1606
|
-
It writes a fixed 1024x768 PNG, screenshot SHA-256 and perceptual dHash, a DOM
|
|
1607
|
-
digest containing hashes and bounded element counts rather than markup or page
|
|
1608
|
-
text, and a version-2 `whoisleuth.web-capture-manifest` compatible with the
|
|
1609
|
-
Cases importer. Version-1 manifests remain importable.
|
|
1610
|
-
|
|
1611
|
-
Rendered capture executes page JavaScript. Each admitted resource operator
|
|
1612
|
-
receives the exact requested URL, including path and query, and ordinary
|
|
1613
|
-
allowlisted request headers; structured manifest and digest fields retain only
|
|
1614
|
-
the target hostname, final HTTP(S) origin, admitted public resource hostnames,
|
|
1615
|
-
and one control-sanitised page title of up to 300 characters, not those paths or queries. The screenshot necessarily
|
|
1616
|
-
preserves visible rendered content and may include page text or a page-reflected
|
|
1617
|
-
path or query until the operator deletes it. It caps HTTP(S) requests and request
|
|
1618
|
-
hostnames, blocks downloads, service workers, dedicated and shared workers, WebSockets, WebRTC, WebTransport,
|
|
1619
|
-
non-read methods, credentials, non-default ports, and private or reserved
|
|
1620
|
-
addresses, and retains no request path, query, headers, bodies, cookies,
|
|
1621
|
-
credentials, DOM markup, or body text in the structured manifest or digest
|
|
1622
|
-
beyond that bounded title. Every browser request is intercepted, its hostname is resolved again,
|
|
1623
|
-
and the bounded response is fetched through WHOISleuth's public-address-pinned
|
|
1624
|
-
transport. Individual responses are capped at 4 MiB and all fetched response
|
|
1625
|
-
bodies together are capped at 24 MiB. Redirect destinations pass through the
|
|
1626
|
-
same interception and validation before collection continues. Use a disposable
|
|
1627
|
-
network-restricted environment for untrusted targets because rendered page code
|
|
1628
|
-
still executes inside the isolated browser process.
|
|
1629
|
-
|
|
1630
|
-
The separate offline comparison command accepts two selected version-2 local
|
|
1631
|
-
capture manifests. It first verifies each referenced screenshot and DOM digest
|
|
1632
|
-
against its declared size, SHA-256, screenshot dimensions, and perceptual hash;
|
|
1633
|
-
it also validates bounded source and limitation metadata and requires the DOM,
|
|
1634
|
-
manifest, and source collection times to agree. It then
|
|
1635
|
-
compares screenshot distance, exact equality of the bounded preorder
|
|
1636
|
-
element-tag sequence and body text-node sequence, bounded element counts, page
|
|
1637
|
-
identity, technologies, and request-domain sets. The tag sequence omits nesting
|
|
1638
|
-
and attributes. The version-1 DOM-digest schema retains the `visibleText` field
|
|
1639
|
-
name for compatibility, but it includes bounded body text nodes that CSS or
|
|
1640
|
-
non-rendered containers may hide and is not a visibility claim.
|
|
1641
|
-
Version-2 comparison output reports only whether the two bounded page titles
|
|
1642
|
-
match; it does not copy either title. It does not recrawl either target, reveal the input paths, or collapse the
|
|
1643
|
-
independent components into a similarity or maliciousness score. A missing
|
|
1644
|
-
perceptual hash remains unavailable rather than becoming a visual difference.
|
|
1645
|
-
|
|
1646
|
-
## Lookup evidence export
|
|
1647
|
-
|
|
1648
|
-
`export` converts one version-1 `whoisleuth.cli.lookup` domain document from a
|
|
1649
|
-
file or stdin into the same versioned `whoisleuth.lookup-evidence` JSON package
|
|
1650
|
-
produced by the web Lookup tool. It performs no lookup and writes only to
|
|
1651
|
-
stdout, so use ordinary shell redirection when a file is wanted. Pretty JSON is
|
|
1652
|
-
the default; `--compact` emits one compact JSON line for pipeline use, while
|
|
1653
|
-
`--markdown` produces a readable source-attributed summary and `--html`
|
|
1654
|
-
produces a self-contained printable report. Compact, Markdown, and HTML output
|
|
1655
|
-
are mutually exclusive. Markdown and HTML include the fixed generator footer
|
|
1656
|
-
by default; `--no-attribution` removes only that footer and is rejected for
|
|
1657
|
-
JSON output.
|
|
1658
|
-
|
|
1659
|
-
The current schema-26 JSON output can be passed directly to
|
|
1660
|
-
`verify-artifact`. The verifier reports `structure_valid` because this format
|
|
1661
|
-
has no embedded checksum or signature. Use a verified investigation manifest
|
|
1662
|
-
and exact manifest-entry identity when byte-for-byte retention matters, and
|
|
1663
|
-
review the bounded privacy-projected registry RDAP publication, normalised
|
|
1664
|
-
WHOIS values, and bounded contacts before sharing. `interchange-report`
|
|
1665
|
-
recognises the current format and describes the
|
|
1666
|
-
browser replay as lossy by design because replay renders bounded normalised
|
|
1667
|
-
facts rather than raw payloads. Schema 25 remains readable when its retained
|
|
1668
|
-
historical wrappers differ from retained diagnostics in the ways emitted by
|
|
1669
|
-
the former producer. The diagnostics remain authoritative, unavailable wrapper
|
|
1670
|
-
data is suppressed during replay, and other contradictory legacy shapes fail
|
|
1671
|
-
closed rather than becoming positive observations.
|
|
1672
|
-
|
|
1673
|
-
The saved input is capped at 8 MiB and scanned before parsing for duplicate
|
|
1674
|
-
object keys, the prototype-sensitive `__proto__` key, more than 48 nesting levels, more than 50,000
|
|
1675
|
-
keys, more than 100,000 values, or more than 10,000 items in one container. It is then revalidated using the same schema, source-status,
|
|
1676
|
-
parsed-data, scalar, list, and event boundaries as `compare`. Portable
|
|
1677
|
-
projection stops at 24 levels and 20,000 entries before recursive copying, and
|
|
1678
|
-
the completed package must pass the same portable-tree assertion used by the
|
|
1679
|
-
browser replay and serializer.
|
|
1680
|
-
The export retains query context, explicitly projected source diagnostics,
|
|
1681
|
-
normalised registry data, a bounded privacy-projected registry RDAP
|
|
1682
|
-
publication, availability analysis, bounded WHOIS referral-hop
|
|
1683
|
-
metadata without response bodies, and the shared
|
|
1684
|
-
registry-source comparison. Version 23 can add the exact local
|
|
1685
|
-
SSLBL comparison already represented by a deep full Lookup. Version 21 adds the bounded registry
|
|
1686
|
-
lifecycle, disclosure, publication-quality, reconciliation, and abuse-routing
|
|
1687
|
-
interpretation derived from the already-collected sources. Registrar RDAP raw
|
|
1688
|
-
data, contacts, entities, links, notices, and source-specific handles remain
|
|
1689
|
-
excluded. Schema version 20 replaces selected security-policy values in
|
|
1690
|
-
retained HTTP evidence
|
|
1691
|
-
with presence-only markers and can include fixed response-policy findings from
|
|
1692
|
-
an already-represented deep lookup. Version 19 additionally retains the bounded credential-surface projection
|
|
1693
|
-
when the saved deep lookup represents it. Version 18 retains the bounded structured identity projection
|
|
1694
|
-
when the saved deep lookup represents it. Version 17 retains the normalised portable-field comparison, explicit
|
|
1695
|
-
source-health states, a strict bounded projection of observed network
|
|
1696
|
-
registration, an optional normalised security.txt disclosure source, HTTPS
|
|
1697
|
-
service-binding publications, and the passive browser-library profile when the
|
|
1698
|
-
saved deep lookup represents them. Raw IP RDAP payloads, security.txt response
|
|
1699
|
-
bodies, script references, matched script content, and contact entities remain
|
|
1700
|
-
excluded.
|
|
1701
|
-
|
|
1702
|
-
Markdown output summarises query context, assessment state, registry sources,
|
|
1703
|
-
source reconciliation, network observations, and collection diagnostics. It
|
|
1704
|
-
escapes all upstream text as untrusted content, bounds displayed values and
|
|
1705
|
-
lists, and deliberately omits raw RDAP JSON and full WHOIS response bodies.
|
|
1706
|
-
Use JSON when the complete evidence package or machine processing is required.
|
|
1707
|
-
The browser Console reuses this bounded Markdown renderer for domain results
|
|
1708
|
-
after first reducing the typed Lookup response to the known normalised fields
|
|
1709
|
-
needed by the report. It separately offers bounded IP and ASN summaries from
|
|
1710
|
-
their normalised RDAP and source-health fields; IP reports can also include
|
|
1711
|
-
bounded reverse-DNS context already collected by Lookup. The browser action
|
|
1712
|
-
does not change the CLI input or output contract.
|
|
1713
|
-
When a version-5, version-6, or version-7 lookup records a documented registry-access constraint, both
|
|
1714
|
-
Markdown and HTML include that context in collection diagnostics without
|
|
1715
|
-
changing its non-authoritative interpretation. Both formats also include the
|
|
1716
|
-
selected address and bounded network registration when present, together with
|
|
1717
|
-
the edge-versus-origin limitation.
|
|
1718
|
-
|
|
1719
|
-
HTML uses the same bounded summary model as Markdown. The generated document
|
|
1720
|
-
contains inline styling for screen and print, but no scripts, forms, active
|
|
1721
|
-
links, or external resources. A restrictive embedded Content Security Policy
|
|
1722
|
-
provides defence in depth when the local file is opened in a browser. All
|
|
1723
|
-
registry values are HTML-escaped and displayed as text.
|
|
1724
|
-
|
|
1725
|
-
This is a deliberately rich evidence package. Raw registry sources can contain
|
|
1726
|
-
publicly published contact data, and deep availability evidence can contain
|
|
1727
|
-
bounded website, DNS, mail, page-identity, and TLS observations. Review and
|
|
1728
|
-
secure the output before sharing it. The CLI does not add browser-only IDN
|
|
1729
|
-
profile analysis, so that optional evidence field is `null`.
|
|
96
|
+
| 0 | The command completed; individual sources can still be partial. |
|
|
97
|
+
| 2 | The command, option or input was invalid. |
|
|
98
|
+
| 3 | Collection, lookup or comparison failed. |
|
|
99
|
+
| 4 | The result was partial or a selected evidence policy was not met. |
|
|
100
|
+
| 70 | The CLI could not complete bootstrap. |
|
|
101
|
+
| 130 | The analyst cancelled; no partial final result was emitted. |
|
|
102
|
+
| 143 | SIGTERM stopped the process; no partial final result was emitted. |
|
|
103
|
+
|
|
104
|
+
## Portable documents and compatibility
|
|
105
|
+
|
|
106
|
+
Readers accept only their declared public and current versions. Unknown,
|
|
107
|
+
unreleased historical and future schemas fail before partial interpretation;
|
|
108
|
+
an invalid import is not treated as an empty document.
|
|
109
|
+
|
|
110
|
+
`inspect-archive` reads current workspace archive v6 and exact public v5. It
|
|
111
|
+
reports section metadata and digest-only search results unless `--reveal` is
|
|
112
|
+
explicitly selected. It never searches notes, contacts or arbitrary raw fields.
|
|
113
|
+
|
|
114
|
+
`export` reads supported saved Lookup v1 or v2 and writes current Lookup
|
|
115
|
+
evidence schema 27. Exact public schema 26 remains readable and can contain
|
|
116
|
+
public contact fields; current schema 27 excludes raw registration payloads,
|
|
117
|
+
expanded contacts, credentials, complete query-bearing URLs and provider
|
|
118
|
+
payloads.
|
|
119
|
+
|
|
120
|
+
`verify-artifact` checks a recognised structure and its applicable integrity
|
|
121
|
+
contract. `interchange-report` describes retained and omitted fields.
|
|
122
|
+
`sign-artifact` and `verify-signature` keep artefact validity, signature
|
|
123
|
+
validity and signer trust separate. None of these checks establishes that
|
|
124
|
+
evidence is accurate, current, safe to share or attributable to a person.
|
|
125
|
+
|
|
126
|
+
## Command-family boundaries
|
|
127
|
+
|
|
128
|
+
- Evidence collection commands retain separate source states. A failed or
|
|
129
|
+
missing supporting source is not converted into absence, availability or a
|
|
130
|
+
favourable score.
|
|
131
|
+
- Discover and Certificate Transparency commands produce review candidates.
|
|
132
|
+
Generation, publication and shared infrastructure do not establish ownership,
|
|
133
|
+
control, activity, intent or maliciousness.
|
|
134
|
+
- Bulk applies one declared collection contract per target. Fast accepts up to
|
|
135
|
+
500 targets and Deep up to 50; each target remains a separate request.
|
|
136
|
+
- Respond commands prepare local Cases, packets and sharing reviews. They do not
|
|
137
|
+
submit, publish, notify or grant recipient authorisation.
|
|
138
|
+
- Assurance, comparison and calibration commands describe supplied or retained
|
|
139
|
+
evidence. They do not tune the running model, change infrastructure or turn an
|
|
140
|
+
analyst label into observed truth.
|
|
141
|
+
- `workflow-plan` lists fixed installed recipes without executing them.
|
|
142
|
+
`workflow-run` executes only installed steps, requires approval for network
|
|
143
|
+
work and pauses for analyst-selection placeholders.
|
|
144
|
+
|
|
145
|
+
Use the installed focused help for positional inputs, exact ceilings, options,
|
|
146
|
+
network effects, outputs and command-specific exit behaviour.
|