@slicedearth/whoisleuth-cli 2.5.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DISCLOSURE +9 -6
- package/NOTICE +3 -2
- package/README.md +60 -67
- package/cli/artifact-validation/case-response.mjs +6 -814
- package/cli/artifact-validation/lookup-evidence.mjs +30 -3
- package/cli/artifact-validation/signed-review.mjs +2 -51
- package/cli/artifact-verify.mjs +41 -3
- package/cli/bulk-command-runner.mjs +4 -6
- package/cli/case-command.mjs +92 -16
- package/cli/case-pack.mjs +14 -3
- package/cli/ci-report.mjs +17 -5
- package/cli/command-definition.mjs +7 -6
- package/cli/discovery-scan-command-runner.mjs +4 -6
- package/cli/doctor.mjs +37 -3
- package/cli/domain-feed.mjs +61 -0
- package/cli/formatters/html.mjs +3 -0
- package/cli/formatters/json.mjs +9 -14
- package/cli/formatters/terminal-lookup.mjs +24 -1
- package/cli/history-command-definitions.mjs +1 -1
- package/cli/indicator-set-command.mjs +1 -2
- package/cli/intake-command.mjs +43 -3
- package/cli/investigation-artifacts.mjs +2 -3
- package/cli/investigation-package-review.mjs +2 -0
- package/cli/investigation-plan.mjs +15 -0
- package/cli/local-mmdb-review.mjs +27 -4
- package/cli/lookup-brief.mjs +11 -5
- package/cli/lookup-command-runner.mjs +21 -13
- package/cli/offline-evidence-review.mjs +51 -5
- package/cli/review-arguments.mjs +3 -2
- package/cli/review-command-definitions.mjs +23 -17
- package/cli/review-command-runner.mjs +6 -3
- package/cli/risk-calibration.mjs +6 -4
- package/cli/saved-lookup.mjs +22 -7
- package/cli/selected-input-worker.mjs +12 -2
- package/cli/source-reliability.mjs +12 -10
- package/cli/support-arguments.mjs +1 -1
- package/cli/support-command-definitions.mjs +5 -4
- package/cli/support-command-runner.mjs +9 -7
- package/cli/watchlist-review.mjs +43 -0
- package/cli/workflow-arguments.mjs +14 -0
- package/cli/workflow-command-definitions.mjs +27 -1
- package/cli/workflow-command-runner.mjs +32 -0
- package/docs/cli-reference.md +49 -11
- package/docs/cli.md +200 -26
- package/docs/contextual-reviews.md +38 -5
- package/docs/infrastructure-observations.md +135 -0
- package/docs/offline-intake-context.md +213 -0
- package/lib/credential-form-attribution.mjs +136 -0
- package/lib/credential-surface-profile.mjs +6 -2
- package/lib/dmarc-discovery.mjs +4 -2
- package/lib/dns-delegation-health.mjs +23 -7
- package/lib/dns-inheritance-review.mjs +14 -1
- package/lib/dns-intelligence.mjs +18 -4
- package/lib/domain-posture-analysis.mjs +53 -2
- package/lib/domain-posture-parsers.mjs +9 -0
- package/lib/domain-posture.mjs +29 -10
- package/lib/evidence-export-privacy.mjs +5 -2
- package/lib/evidence-export.mjs +10 -4
- package/lib/evidence-report.mjs +3 -1
- package/lib/favicon.mjs +13 -4
- package/lib/generated/cisa-kev-catalog.mjs +17 -4
- package/lib/generated/registrar-standing-catalogue.mjs +7 -7
- package/lib/generated/retire-browser-catalog.mjs +178 -5
- package/lib/html-signals.mjs +6 -0
- package/lib/idn-confusables.mjs +5 -1
- package/lib/lookup-child-profile-contract.mjs +28 -11
- package/lib/lookup-collection-receipt.mjs +52 -0
- package/lib/lookup-diagnostics.mjs +2 -12
- package/lib/lookup-progress.mjs +29 -31
- package/lib/lookup-response-contract.mjs +10 -0
- package/lib/lookup-response.mjs +15 -14
- package/lib/lookup-source-progress.mjs +4 -2
- package/lib/lookup.mjs +33 -2
- package/lib/operation-budget.mjs +4 -0
- package/lib/rdap-capabilities.mjs +43 -9
- package/lib/registry-insights.mjs +17 -6
- package/lib/service-binding-dns.mjs +19 -2
- package/lib/sslbl-certificates.generated.mjs +142 -140
- package/lib/static-html-analysis.mjs +32 -4
- package/lib/technology-evidence-role.mjs +1 -51
- package/lib/tls-intelligence.mjs +30 -5
- package/lib/website-enrichment.mjs +39 -23
- package/lib/whois-authority.mjs +56 -1
- package/lib/whois-chain.mjs +14 -4
- package/lib/whois-common-formats.mjs +3 -1
- package/lib/whois-contacts.mjs +13 -2
- package/lib/whois-contracts.mjs +2 -0
- package/lib/whois-normalization.mjs +4 -4
- package/package.json +9 -7
- package/packages/analysis/bounded-json.mjs +12 -2
- package/packages/analysis/risk-scoring.mjs +12 -9
- package/packages/cases/case-attachment-model.mjs +36 -1
- package/packages/cases/case-checkpoint-receipts.mjs +68 -0
- package/packages/cases/case-containment-handoff.mjs +195 -0
- package/packages/cases/case-evidence-links.mjs +44 -0
- package/packages/cases/case-evidence-model.mjs +51 -7
- package/packages/cases/case-migration-model.mjs +9 -1
- package/packages/cases/case-object-coverage.mjs +119 -0
- package/packages/cases/case-packet-correction.mjs +106 -0
- package/packages/cases/case-recheck-model.mjs +35 -5
- package/packages/cases/case-record-operations.mjs +87 -9
- package/packages/cases/case-record-projection.mjs +43 -5
- package/packages/cases/case-record-version-input.mjs +23 -1
- package/packages/cases/case-report.mjs +35 -4
- package/packages/cases/case-requested-evidence.mjs +1 -1
- package/packages/cases/case-response-actions.mjs +57 -1
- package/packages/cases/case-response-model.mjs +7 -0
- package/packages/cases/case-response-object.mjs +119 -0
- package/packages/cases/case-response-outcomes.mjs +81 -14
- package/packages/cases/case-response-packet-render.mjs +22 -3
- package/packages/cases/case-response-packet-validation.mjs +880 -0
- package/packages/cases/case-response-packet-vocabulary.mjs +12 -1
- package/packages/cases/case-response-packet.mjs +32 -17
- package/packages/cases/case-response-review-inputs.mjs +66 -8
- package/packages/cases/case-type-presentation.mjs +10 -0
- package/packages/cases/case-workflow-metadata.mjs +1 -17
- package/packages/comparison/capture-context.mjs +3 -2
- package/packages/contracts/analyst-interchange.mjs +7 -5
- package/packages/contracts/analyst-review-state-contract.mjs +1 -1
- package/packages/contracts/candidate-watch-review.mjs +54 -0
- package/packages/contracts/case-portability.mjs +292 -43
- package/packages/contracts/cli-command-semantics.mjs +3 -0
- package/packages/contracts/cli-doctor.mjs +4 -0
- package/packages/contracts/cli-lookup.mjs +57 -46
- package/packages/contracts/context-review.mjs +2 -1
- package/packages/contracts/external-observation-interchange.mjs +96 -28
- package/packages/contracts/lookup-evidence.mjs +13 -2
- package/packages/contracts/message-intake.mjs +7 -1
- package/packages/contracts/registry-insights.mjs +6 -0
- package/packages/contracts/risk-calibration.mjs +44 -29
- package/packages/contracts/schema-lifecycle.mjs +3 -1
- package/packages/contracts/web-capture.mjs +1 -1
- package/packages/contracts/workspace-portability.mjs +86 -16
- package/packages/evidence/collection-quality.mjs +1 -1
- package/packages/evidence/credential-form-attribution.mjs +60 -0
- package/packages/evidence/dmarc-policy-context.mjs +80 -0
- package/packages/evidence/image-regions.mjs +15 -0
- package/packages/evidence/lookup-collection-receipt.mjs +140 -0
- package/packages/evidence/lookup-collection-review.mjs +74 -0
- package/packages/evidence/record-identity.mjs +60 -16
- package/packages/evidence/technology-evidence-role.mjs +51 -0
- package/packages/interchange/external-findings-import.mjs +40 -21
- package/packages/interchange/json-output.mjs +14 -0
- package/packages/interchange/managed-indicator-export.mjs +3 -2
- package/packages/interchange/managed-indicator-set.mjs +13 -0
- package/packages/investigation/acquisition-decision-packet.mjs +78 -0
- package/packages/investigation/bulk-mail-exposure.mjs +2 -2
- package/packages/investigation/context-review.mjs +3 -3
- package/packages/investigation/document-intake.mjs +9 -3
- package/packages/investigation/domain-history-review.mjs +50 -12
- package/packages/investigation/domain-transition-review.mjs +2 -0
- package/packages/investigation/infrastructure-observation.mjs +234 -0
- package/packages/investigation/intake-context.mjs +284 -0
- package/packages/investigation/intake-indicators.mjs +116 -0
- package/packages/investigation/intake-phones.mjs +155 -0
- package/packages/investigation/intake-report.mjs +2 -1
- package/packages/investigation/investigation-manifest.mjs +33 -7
- package/packages/investigation/link-intake.mjs +38 -8
- package/packages/investigation/message-intake.mjs +55 -15
- package/packages/monitoring/domain-feed.mjs +321 -0
- package/packages/workspace/brand-candidate-workflow.mjs +351 -0
- package/packages/workspace/brand-keyword-campaign.mjs +241 -0
- package/packages/workspace/brand-profile-model.mjs +46 -2
- package/packages/workspace/bulk-session-model.mjs +12 -0
- package/packages/workspace/candidate-watch-handoff.mjs +195 -0
- package/packages/workspace/detection-rule-model.mjs +10 -2
- package/packages/workspace/shortlist-model.mjs +10 -2
- package/packages/workspace/watchlist-history.mjs +31 -4
- package/packages/workspace/watchlist-store.mjs +136 -7
- package/third-party-notices.txt +30 -30
|
@@ -3,7 +3,19 @@ import { CliUsageError } from "./errors.mjs";
|
|
|
3
3
|
import {} from "./fail-policy.mjs";
|
|
4
4
|
import { commandDefaultNumber } from "./command-reference.mjs";
|
|
5
5
|
import { WORKFLOW_COMMAND_DEFINITIONS } from "./workflow-command-definitions.mjs";
|
|
6
|
+
import { parseDomainFeedSelectors } from "./domain-feed.mjs";
|
|
6
7
|
import { terminalOptions, jsonOutput, failPolicies, parseOutput, } from "./argument-values.mjs";
|
|
8
|
+
function parseDomainFeedArguments(parsed) {
|
|
9
|
+
const operation = parsed.positionalValue('operation');
|
|
10
|
+
const contextSource = parsed.positionalValue('context');
|
|
11
|
+
if ((operation === 'watch-input') !== Boolean(contextSource))
|
|
12
|
+
throw new CliUsageError('watch-input requires one existing candidate-watch-input context file; review does not accept a context file.');
|
|
13
|
+
return { action: 'domain-feed', operation, feedId: parsed.positionalValue('feed'), source: parsed.positionalValue('source'), contextSource,
|
|
14
|
+
selection: parseDomainFeedSelectors(parsed.optionValues('--select')), output: jsonOutput(parsed), ...terminalOptions(parsed) };
|
|
15
|
+
}
|
|
16
|
+
function parseWatchlistReviewArguments(parsed) {
|
|
17
|
+
return { action: 'watchlist-review', operation: parsed.positionalValue('operation'), source: parsed.positionalValue('source'), output: jsonOutput(parsed), ...terminalOptions(parsed) };
|
|
18
|
+
}
|
|
7
19
|
function parseMonitorOnceArguments(parsed) {
|
|
8
20
|
const selectedFailPolicies = failPolicies(parsed, 'monitor-once');
|
|
9
21
|
return {
|
|
@@ -80,6 +92,8 @@ function parseWorkflowRunArguments(parsed) {
|
|
|
80
92
|
};
|
|
81
93
|
}
|
|
82
94
|
export const WORKFLOW_ARGUMENT_PARSERS = Object.freeze({
|
|
95
|
+
'domain-feed': parseDomainFeedArguments,
|
|
96
|
+
'watchlist-review': parseWatchlistReviewArguments,
|
|
83
97
|
'monitor-once': parseMonitorOnceArguments,
|
|
84
98
|
'workflow-plan': parseWorkflowPlanArguments,
|
|
85
99
|
'workflow-run': parseWorkflowRunArguments,
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { INVESTIGATION_PLAN_RECIPES, RUNNABLE_INVESTIGATION_PLAN_RECIPES } from "./investigation-recipes.mjs";
|
|
2
|
-
import { positional, OPTIONAL_FILE_POSITIONAL, constraint, commandSeed, integer, BASE_INTEGER_RANGE, file } from "./command-definition.mjs";
|
|
2
|
+
import { positional, OPTIONAL_FILE_POSITIONAL, constraint, commandSeed, integer, BASE_INTEGER_RANGE, file, optionDefinition } from "./command-definition.mjs";
|
|
3
|
+
import { DOMAIN_FEED_CATALOGUE } from "../packages/monitoring/domain-feed.mjs";
|
|
4
|
+
import { WATCHLIST_SCHEMA_VERSION } from "../packages/contracts/workspace-portability.mjs";
|
|
3
5
|
export const WORKFLOW_COMMAND_DEFINITIONS = Object.freeze({
|
|
6
|
+
'domain-feed': commandSeed({
|
|
7
|
+
reference: { description: 'Review exact hosts or literal terms in a selected local plain-domain feed.',
|
|
8
|
+
example: 'whoisleuth domain-feed review tif-mini feed.txt --select host:candidate.example --json',
|
|
9
|
+
boundary: 'Always available offline. Reads one explicit local regular file; never downloads a feed, performs a Lookup, changes scores, retains candidates or enables a schedule. Streams at most 256 MiB and 10 million physical rows with 1,024-byte lines and a ten-minute deadline; retains at most 200 matched hosts. Repeat --select host:<hostname>, term:<literal> or exclude:<literal> for at most 200 exact hosts, 20 positive and 20 negative literal terms of 3–80 characters. A negative match vetoes even an exact host before the match bound; at least one positive term or exact host is required. Matching uses canonical ASCII/punycode substrings, never token boundaries, parent equivalence, typo/confusable expansion or regular expressions. Review emits the full raw-byte digest, separate declared file/local clocks, unknown per-host clocks and omissions. watch-input also requires a candidate-watch-input v1 context file with an empty candidates array, and emits that existing format for a separate watchlist-review plan/export. Inclusion is not a maliciousness, activity, ownership or availability verdict.' },
|
|
10
|
+
collection: { scope: 'Local raw file: 256 MiB, 10 million physical rows, 1,024 bytes per line, ten minutes; 200 retained hosts, 20 positive and 20 negative literal terms, no requests.' },
|
|
11
|
+
summary: 'Review a selected local plain-domain feed', options: ['--select', '--json', '--quiet', '--no-color'],
|
|
12
|
+
optionOverrides: { '--select': optionDefinition('text', 'Select host:<exact-hostname>, term:<literal-text> or exclude:<literal-text>; repeat for separate explicit selectors.', { occurrence: 'repeatable', acceptsOptionLikeValue: true }) },
|
|
13
|
+
positionals: Object.freeze([positional('operation', 'enum', 1, 1, ['review', 'watch-input']),
|
|
14
|
+
positional('feed', 'enum', 1, 1, DOMAIN_FEED_CATALOGUE.map(feed => feed.id)), positional('source', 'file', 1, 1), positional('context', 'file', 0, 1)]),
|
|
15
|
+
constraints: Object.freeze([constraint({ kind: 'required', options: ['--select'] })]),
|
|
16
|
+
handlerOwner: 'workflow', networkEffect: 'offline', common: false,
|
|
17
|
+
schemaIdentifiers: Object.freeze(['whoisleuth.candidate-watch-input']), primaryArtefacts: Object.freeze(['Bounded feed inclusion review', 'Explicit candidate watch selection']),
|
|
18
|
+
planSupport: true, additionalOutputFormats: Object.freeze([]), bootstrapProfile: 'allowed',
|
|
19
|
+
}),
|
|
20
|
+
'watchlist-review': commandSeed({
|
|
21
|
+
reference: { description: 'Preview or export an explicit candidate selection to a local watchlist.', example: 'whoisleuth watchlist-review plan selection.json --json',
|
|
22
|
+
boundary: `Reads bounded local JSON only. Plan shows exact domains, duplicates, per-domain outcomes, destination and review priority with zero additional requests. Export emits Watchlist schema ${WATCHLIST_SCHEMA_VERSION} without creating a scan or baseline. Neither mode enables collection or scheduling.` },
|
|
23
|
+
collection: { scope: 'At most 2,000 selected candidate domains; no target requests.' },
|
|
24
|
+
summary: 'Review a local candidate watchlist handoff', options: ['--json', '--quiet', '--no-color'],
|
|
25
|
+
positionals: Object.freeze([positional('operation', 'enum', 1, 1, ['plan', 'export']), positional('source', 'file', 0, 1, [], 'argv_or_stdin')]),
|
|
26
|
+
constraints: Object.freeze([]), handlerOwner: 'workflow', networkEffect: 'offline', common: false,
|
|
27
|
+
schemaIdentifiers: Object.freeze(['whoisleuth.candidate-watch-input', 'whoisleuth.watchlists']), primaryArtefacts: Object.freeze(['Exact candidate handoff plan', 'Local watchlist export']),
|
|
28
|
+
planSupport: true, additionalOutputFormats: Object.freeze([]), bootstrapProfile: 'allowed',
|
|
29
|
+
}),
|
|
4
30
|
"monitor-once": commandSeed({
|
|
5
31
|
reference: {
|
|
6
32
|
description: 'Collect one bounded owned-domain review and compare it with an optional prior checkpoint.',
|
|
@@ -16,7 +16,37 @@ import { MAX_SHARING_REVIEW_BYTES } from "./sharing-review.mjs";
|
|
|
16
16
|
import { createBufferedOutput } from "./output-file.mjs";
|
|
17
17
|
import { boundedInteractiveAnswer, canReadInteractiveLine, readBoundedInteractiveLine } from "./terminal-input.mjs";
|
|
18
18
|
import { WORKFLOW_INLINE_COMMANDS } from "./inline-command-families.mjs";
|
|
19
|
+
import { reviewCandidateWatchInput, parseCandidateWatchInput } from "./watchlist-review.mjs";
|
|
20
|
+
import { readDomainFeedFile } from "./domain-feed.mjs";
|
|
21
|
+
import { scanDomainFeed, buildDomainFeedWatchInput, normalizeDomainFeedSelection } from "../packages/monitoring/domain-feed.mjs";
|
|
22
|
+
import { MAX_WATCHLIST_IMPORT_BYTES } from "../packages/contracts/workspace-portability.mjs";
|
|
19
23
|
import { runDiscriminatedCommandHandler } from "./discriminated-command-handlers.mjs";
|
|
24
|
+
async function runWatchlistReviewCommand(args, dependencies, context) {
|
|
25
|
+
const raw = dependencies.readArtifactInput ? await dependencies.readArtifactInput(args.source) : await context.readInput(args.source, MAX_WATCHLIST_IMPORT_BYTES, 'Candidate watch selection');
|
|
26
|
+
const document = reviewCandidateWatchInput(raw, args.operation, context.now());
|
|
27
|
+
if (!args.quiet)
|
|
28
|
+
context.writeStdout(formatJsonDocument(document));
|
|
29
|
+
return EXIT_CODES.SUCCESS;
|
|
30
|
+
}
|
|
31
|
+
async function runDomainFeedCommand(args, dependencies, context) {
|
|
32
|
+
context.setFailureLabel('Offline domain-feed review');
|
|
33
|
+
const handoff = args.contextSource ? parseCandidateWatchInput(dependencies.readArtifactInput
|
|
34
|
+
? await dependencies.readArtifactInput(args.contextSource)
|
|
35
|
+
: await context.readInput(args.contextSource, MAX_WATCHLIST_IMPORT_BYTES, 'Candidate watch context')) : null;
|
|
36
|
+
const watchSelection = handoff?.selection;
|
|
37
|
+
if (watchSelection && watchSelection.candidates.length)
|
|
38
|
+
throw new CliUsageError('The watch-input context must have an empty candidates array; only reviewed feed matches may be nominated.');
|
|
39
|
+
const selection = normalizeDomainFeedSelection({ ...args.selection, brandProfileId: watchSelection?.brandProfileId ?? null });
|
|
40
|
+
const review = await scanDomainFeed((dependencies.readDomainFeedInput ?? readDomainFeedFile)(args.source, dependencies.signal), {
|
|
41
|
+
feedId: args.feedId, selection, importedAt: context.now(), ...(dependencies.signal ? { signal: dependencies.signal } : {}),
|
|
42
|
+
});
|
|
43
|
+
const document = watchSelection && handoff
|
|
44
|
+
? buildDomainFeedWatchInput(review, review.matches.map(match => match.domain), watchSelection, handoff.watchlists)
|
|
45
|
+
: review;
|
|
46
|
+
if (!args.quiet)
|
|
47
|
+
context.writeStdout(formatJsonDocument(document));
|
|
48
|
+
return EXIT_CODES.SUCCESS;
|
|
49
|
+
}
|
|
20
50
|
function boundWorkflowInputs(command, inputs, dependencies, context) {
|
|
21
51
|
if (!inputs.size)
|
|
22
52
|
return {};
|
|
@@ -181,6 +211,8 @@ async function runWorkflowRecipeCommand(args, dependencies, context) {
|
|
|
181
211
|
return investigationRunExitCode(document);
|
|
182
212
|
}
|
|
183
213
|
const WORKFLOW_COMMAND_HANDLERS = Object.freeze({
|
|
214
|
+
'domain-feed': runDomainFeedCommand,
|
|
215
|
+
'watchlist-review': runWatchlistReviewCommand,
|
|
184
216
|
'monitor-once': runMonitorOnceCommand,
|
|
185
217
|
'workflow-plan': runWorkflowPlanCommand,
|
|
186
218
|
'workflow-run': runWorkflowRecipeCommand,
|
package/docs/cli-reference.md
CHANGED
|
@@ -71,11 +71,11 @@ candidate, form destination and deliberately observed navigation separately
|
|
|
71
71
|
attributed. A similar page without a logo or brand name can still merit manual
|
|
72
72
|
evidence review; correspondence does not establish authorship, rights authority
|
|
73
73
|
or maliciousness. Missing optional capture or comparison evidence does not
|
|
74
|
-
prevent ordinary
|
|
74
|
+
prevent ordinary case pins and conclusions. Installed command help remains the
|
|
75
75
|
authority for offline file inputs and explicit collection plans.
|
|
76
76
|
|
|
77
77
|
The [reporting guide](https://www.whoisleuth.com/resources/reporting-and-takedown-guidance)
|
|
78
|
-
uses the same reviewed official-route catalogue as the
|
|
78
|
+
uses the same reviewed official-route catalogue as the console for social
|
|
79
79
|
content, storefronts, app listings, hosted files/forms and advertising. Verify
|
|
80
80
|
the exact object, current route, reporter authority and disclosure before any
|
|
81
81
|
manual submission. Fraud, order complaints and rights notices are different
|
|
@@ -96,8 +96,10 @@ PKIX, STARTTLS and SMTP transport remain separate evidence states.
|
|
|
96
96
|
STARTTLS detection uses the full bounded reply. If the retained capability
|
|
97
97
|
inventory is shortened, the report remains partial and names the omission.
|
|
98
98
|
|
|
99
|
-
The
|
|
100
|
-
|
|
99
|
+
The separate optional rendered-capture companion is distributed as a locally
|
|
100
|
+
assembled archive, not as part of the hosted application or main CLI, and is
|
|
101
|
+
not published to a package registry. Its sandboxed, bounded browser executes
|
|
102
|
+
remote page JavaScript only for an explicitly
|
|
101
103
|
authorised route set, and each admitted resource operator receives the exact
|
|
102
104
|
requested URL. Captures and screenshots remain local until the operator deletes
|
|
103
105
|
them.
|
|
@@ -143,18 +145,46 @@ Readers accept only their declared public and current versions. Unknown,
|
|
|
143
145
|
unreleased historical and future schemas fail before partial interpretation;
|
|
144
146
|
an invalid import is not treated as an empty document.
|
|
145
147
|
|
|
146
|
-
`inspect-archive` reads current workspace archive
|
|
148
|
+
`inspect-archive` reads current workspace archive v10 and exact versions 5–9. It
|
|
147
149
|
reports section metadata and digest-only search results unless `--reveal` is
|
|
148
150
|
explicitly selected. It never searches notes, contacts or arbitrary raw fields.
|
|
149
151
|
|
|
150
|
-
`export` reads supported saved Lookup
|
|
151
|
-
evidence schema
|
|
152
|
-
readable. Versions 27–
|
|
152
|
+
`export` reads supported saved Lookup versions 1–3 and writes current Lookup
|
|
153
|
+
evidence schema 31. Supported schemas 27–30 and exact v1 schema 26 remain
|
|
154
|
+
readable. Versions 27–31 exclude raw registration payloads, expanded
|
|
153
155
|
contacts, credentials, complete query-bearing URLs and provider payloads;
|
|
154
|
-
|
|
156
|
+
Schemas 28 and later also retain the bounded registrar-standing projection.
|
|
155
157
|
Schema 29 identifies the hostname used for DNS, TLS and web observations,
|
|
156
158
|
separately from the registrable domain used by registration sources. Older
|
|
157
159
|
evidence retains its original collection scope.
|
|
160
|
+
Schema 31 retains WHOIS registration classification separately from collection
|
|
161
|
+
completion. Lifecycle interpretation requires positive registration evidence;
|
|
162
|
+
a completed negative or inconclusive WHOIS reply does not establish registration
|
|
163
|
+
or absence of locks. Earlier exports retain their exact original interpretation
|
|
164
|
+
for historical verification and are not silently relabelled.
|
|
165
|
+
|
|
166
|
+
New WHOIS collection distinguishes confirmed no-service discovery from an
|
|
167
|
+
incomplete discovery response. Empty, refused or unrecognised bootstrap
|
|
168
|
+
responses remain partial; they do not establish that WHOIS is unsupported.
|
|
169
|
+
`--strict-exit` treats that incomplete attempt as a source failure. Explicit
|
|
170
|
+
no-request access-policy restrictions remain distinct from transport failures.
|
|
171
|
+
|
|
172
|
+
Saved Lookup version 3 can retain a bounded collection receipt: original
|
|
173
|
+
optional selections, admitted source families, collector starts, outcomes and
|
|
174
|
+
explicitly known completeness. `lookup --verbose` and `lookup --browse`
|
|
175
|
+
show this account with source-specific explanations and qualified retry guidance.
|
|
176
|
+
Earlier files have no inferred receipt. The receipt contains
|
|
177
|
+
no target values, URLs, contacts or raw errors and does not prove network
|
|
178
|
+
delivery. It stays in full private Lookup JSON; the minimised `export` report
|
|
179
|
+
does not include it. `--plan` remains offline and produces no completed receipt.
|
|
180
|
+
|
|
181
|
+
Case schema 20 also retains this context when an analyst saves a completed Lookup
|
|
182
|
+
assessment or selected checkpoint facts. A selected checkpoint saves only its
|
|
183
|
+
selected pins and one payload-free receipt, not every Lookup result. Ordinary
|
|
184
|
+
backups and internal case packs preserve it. Trusted/public case packs, case
|
|
185
|
+
reports and response packets omit receipts; shared assessment identities are
|
|
186
|
+
recomputed without them. Historical case formats remain readable without
|
|
187
|
+
inventing missing collection choices.
|
|
158
188
|
|
|
159
189
|
`verify-artifact` checks a recognised structure and its applicable integrity
|
|
160
190
|
contract. `interchange-report` describes retained and omitted fields.
|
|
@@ -162,6 +192,14 @@ contract. `interchange-report` describes retained and omitted fields.
|
|
|
162
192
|
validity and signer trust separate. None of these checks establishes that
|
|
163
193
|
evidence is accurate, current, safe to share or attributable to a person.
|
|
164
194
|
|
|
195
|
+
The text output of `verify-artifact` suggests compatible offline follow-up
|
|
196
|
+
commands for recognised saved Lookups, case exports, workspace archives,
|
|
197
|
+
Lookup-evidence reports, Case-packs and managed indicator revisions. These are
|
|
198
|
+
examples with placeholder filenames, not executed actions or a sharing approval.
|
|
199
|
+
Replace the filenames deliberately; a case or indicator inspection can display
|
|
200
|
+
private contents. Encrypted workspace guidance uses a separate passphrase file,
|
|
201
|
+
never a passphrase in command history. JSON output and `--quiet` are unchanged.
|
|
202
|
+
|
|
165
203
|
### Signer trust
|
|
166
204
|
|
|
167
205
|
Use `verify-signature package.json --trust-store-file trust.json --json` to
|
|
@@ -211,9 +249,9 @@ own retention policy. No automatic key discovery, key storage or trust refresh o
|
|
|
211
249
|
control, activity, intent or maliciousness.
|
|
212
250
|
- Bulk applies one declared collection contract per target. Fast accepts up to
|
|
213
251
|
500 targets and Deep up to 50; each target remains a separate request.
|
|
214
|
-
- Respond commands package browser-created
|
|
252
|
+
- Respond commands package browser-created cases and prepare local packets,
|
|
215
253
|
reports and sharing reviews. The offline [`case` workflow](cli.md#local-case-files)
|
|
216
|
-
also creates and updates ordinary local
|
|
254
|
+
also creates and updates ordinary local case files through explicit, conflict-checked
|
|
217
255
|
output. Neither workflow submits, publishes, notifies or grants recipient authorisation.
|
|
218
256
|
- Assurance, comparison and calibration commands describe supplied or retained
|
|
219
257
|
evidence. They do not tune the running model, change infrastructure or turn an
|
package/docs/cli.md
CHANGED
|
@@ -12,6 +12,11 @@ tasks, then offers searchable commands with examples, option explanations and
|
|
|
12
12
|
defaults. Command-section links can be bookmarked. Its option guidance and
|
|
13
13
|
installed help derive from the same command definitions.
|
|
14
14
|
|
|
15
|
+
Not sure which interface to use? The [installation-mode comparison](https://www.whoisleuth.com/cli#choose-mode)
|
|
16
|
+
covers the hosted console, filesystem-local application, CLI and capture companion,
|
|
17
|
+
including request origin, storage, offline use and distribution. The optional
|
|
18
|
+
application and capture archives are separate from the public CLI package.
|
|
19
|
+
|
|
15
20
|
The generated [privacy and data-flow catalogue](https://github.com/slicedearth/whoisleuth/blob/main/docs/privacy-data-flow-catalogue.md)
|
|
16
21
|
lists the network, recipient, retention and export boundary for every command.
|
|
17
22
|
|
|
@@ -75,22 +80,35 @@ private document from the interactive view:
|
|
|
75
80
|
|
|
76
81
|
```bash
|
|
77
82
|
whoisleuth lookup example.test --deep --browse --save-lookup lookup.json
|
|
83
|
+
whoisleuth verify-artifact lookup.json --json
|
|
84
|
+
whoisleuth export lookup.json --output evidence.json
|
|
85
|
+
whoisleuth verify-artifact evidence.json --json
|
|
78
86
|
```
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
its digest and source states,
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
Keep `lookup.json` as the private CLI original. In Lookup in the console, open **Replay
|
|
89
|
+
exported evidence**, select `evidence.json`, check its digest and source states,
|
|
90
|
+
then create or update a browser-local case. The private CLI document is not a
|
|
91
|
+
browser replay format; the separate evidence export excludes raw registration
|
|
92
|
+
payloads and expanded contacts. Neither file is uploaded. Case classification, exact incident links and response
|
|
93
|
+
actions remain deliberate analyst steps. Ordinary case files also support the
|
|
84
94
|
offline CLI workflow below.
|
|
85
|
-
When several incident
|
|
86
|
-
retaining replay evidence. Case packs preserve each current
|
|
95
|
+
When several incident cases share a domain, select the intended case before
|
|
96
|
+
retaining replay evidence. Case packs preserve each current case ID separately;
|
|
87
97
|
trusted and public packs exclude analyst-entered incident titles.
|
|
88
98
|
Every audience retains tags, decision summaries and rationale as well as domain
|
|
89
|
-
evidence and
|
|
99
|
+
evidence and case, pin and decision IDs. Public does not mean anonymous.
|
|
90
100
|
Browser Lookup evidence can be verified or packaged in the CLI. `brief`,
|
|
91
101
|
`export`, `compare`, `registry-doctor` and `source-report` instead require a
|
|
92
102
|
saved CLI Lookup; they do not reconstruct it from a browser export.
|
|
93
103
|
|
|
104
|
+
Registration source states are independent: `unsupported` means no RDAP or
|
|
105
|
+
WHOIS service is published for the target, while `skipped` means no query was
|
|
106
|
+
issued in that mode or under the registry access policy. Neither is a transport
|
|
107
|
+
failure or a domain-absence finding. Standard terminal output explains these
|
|
108
|
+
non-query outcomes; JSON and evidence exports retain their separate states.
|
|
109
|
+
`--strict-exit` does not fail solely because a protocol is unsupported or skipped,
|
|
110
|
+
but continues to report genuine failed or partial sources.
|
|
111
|
+
|
|
94
112
|
Process selected local input:
|
|
95
113
|
|
|
96
114
|
```bash
|
|
@@ -106,6 +124,18 @@ One strict domain, IP address or ASN can occupy command position as Lookup
|
|
|
106
124
|
shorthand. URL-like or ambiguous input requires the explicit `lookup` command.
|
|
107
125
|
Only `bulk` accepts multiple targets.
|
|
108
126
|
|
|
127
|
+
For a downloaded plain-domain feed, use
|
|
128
|
+
`whoisleuth domain-feed review nrd7 feed.txt --select term:example --json`.
|
|
129
|
+
Repeat `--select exclude:literal` to veto a literal substring before the result
|
|
130
|
+
bound, including for exact-host selections. At most 20 positive and 20 negative
|
|
131
|
+
terms of 3–80 characters are supported; at least one positive term or exact host
|
|
132
|
+
is required. Matching uses canonical ASCII/punycode text without token, typo,
|
|
133
|
+
confusable or regular-expression expansion. These offline selectors do not infer
|
|
134
|
+
saved browser campaign identity or default priority.
|
|
135
|
+
This is an offline literal match, not a feed download or target Lookup. The
|
|
136
|
+
[candidate-review guide](https://github.com/slicedearth/whoisleuth/blob/main/docs/brand-candidate-review.md#review-a-domain-feed) covers
|
|
137
|
+
source attribution and the separate Watchlist handoff.
|
|
138
|
+
|
|
109
139
|
`discover` accepts a brand label or registrable domain and supports multi-part
|
|
110
140
|
public suffixes in `--tlds` (for example, `co.uk,com.au`). It preserves the full
|
|
111
141
|
suffix and does not collect candidate evidence; use `discover-scan` only after
|
|
@@ -132,6 +162,8 @@ For an explicit inherited-policy and direct parent-delegation review, use
|
|
|
132
162
|
option, posture collection keeps its existing exact-name scope. The extra
|
|
133
163
|
results distinguish recursive policy publication from sampled parent referrals;
|
|
134
164
|
they do not establish name existence, message authentication or DNSSEC validity.
|
|
165
|
+
The machine-readable posture document keeps its existing versioned fields;
|
|
166
|
+
the website's transient structured policy scope is not included in that export.
|
|
135
167
|
|
|
136
168
|
| Mode | Behaviour |
|
|
137
169
|
| --- | --- |
|
|
@@ -146,6 +178,16 @@ their focused help. They do not use the hosted login or hosted usage controls.
|
|
|
146
178
|
`lookup --plan` lists planned source families and disclosure targets before
|
|
147
179
|
collection. `doctor` is offline unless `--network` is selected.
|
|
148
180
|
|
|
181
|
+
For troubleshooting that you intend to share, use
|
|
182
|
+
`whoisleuth doctor --summary-json > diagnostics.json`. This summary keeps numeric
|
|
183
|
+
CLI/Node versions, fixed check codes and public format identifiers from the command
|
|
184
|
+
catalogue. Those identifiers describe declared formats, not a compatibility test.
|
|
185
|
+
Targets, URLs, filenames, paths, user names, credentials, headers, timestamps and
|
|
186
|
+
free-form diagnostic details are omitted. Version prerelease/build metadata is
|
|
187
|
+
also omitted. Normal terminal and `--json` diagnostics can include error details;
|
|
188
|
+
inspect them before sharing. The summary does not enable network checks or upload
|
|
189
|
+
anything, and it has the same success/partial exit behaviour as the detailed report.
|
|
190
|
+
|
|
149
191
|
Deep Lookup reports IPv4 and IPv6 results separately, including empty answers,
|
|
150
192
|
NODATA, resolver-reported missing names and query failures. These outcomes remain
|
|
151
193
|
distinct in evidence exports; none alone establishes domain removal.
|
|
@@ -179,6 +221,30 @@ Excluded links and unsupported QR payloads make the review partial, with
|
|
|
179
221
|
category counts rather than private payload text. Bare QR hostnames are not
|
|
180
222
|
automatically treated as URLs.
|
|
181
223
|
|
|
224
|
+
Current message-intake reports also retain bounded literal IPv4/IPv6 and
|
|
225
|
+
explicitly labelled MD5, SHA-1 and SHA-256 observations from supported body and
|
|
226
|
+
document text. Each observation links to its selected source part and digest;
|
|
227
|
+
it is not a Lookup target, file identification or threat verdict. Complete URLs,
|
|
228
|
+
message headers, QR payloads, HAR and identity-event fields are excluded from
|
|
229
|
+
this text scan. Historical version-1 reports do not acquire new observations.
|
|
230
|
+
|
|
231
|
+
Use `intake text selected.txt --intake-context context.json --json` to add an
|
|
232
|
+
explicit analyst-supplied distribution declaration. The separate context file
|
|
233
|
+
is limited to 8 KiB and cannot use stdin. Its channel, non-sensitive source
|
|
234
|
+
label and optional declared time, reference, observer and vantage labels are
|
|
235
|
+
included in the output, not verified as delivery or capture conditions. See
|
|
236
|
+
[selected-input indicators and declarations](offline-intake-context.md) for the
|
|
237
|
+
exact schema, privacy exclusions and extraction bounds.
|
|
238
|
+
|
|
239
|
+
Plain-text phone discovery reports only candidate counts, the source digest and
|
|
240
|
+
UTF-16 selection ranges to standard error; unselected numbers do not enter JSON
|
|
241
|
+
output. Use a version-2 `--intake-context` file to select exact ranges and declare
|
|
242
|
+
their source, basis, role and known time. The same optional file can supply a
|
|
243
|
+
displayed/destination pair for local hostname comparison. See the
|
|
244
|
+
[selection example](offline-intake-context.md#select-phone-observations-in-the-cli).
|
|
245
|
+
`--quiet` suppresses discovery guidance, and `--strict-exit` reports partial
|
|
246
|
+
phone coverage as well as other incomplete intake work.
|
|
247
|
+
|
|
182
248
|
### Local IP-location database review
|
|
183
249
|
|
|
184
250
|
`review-evidence query.json --mmdb selected.mmdb --json --strict-exit` reads
|
|
@@ -227,12 +293,29 @@ metadata or freshness admission; terminal output identifies that limitation.
|
|
|
227
293
|
|
|
228
294
|
### Contextual reviews
|
|
229
295
|
|
|
296
|
+
`review-evidence` reviews bounded source-qualified infrastructure snapshots and explicit earlier/later comparisons offline. See [infrastructure observations](infrastructure-observations.md) for supported inputs and how to interpret their outcomes.
|
|
297
|
+
|
|
230
298
|
`review-evidence` also accepts [contextual review inputs](contextual-reviews.md)
|
|
231
299
|
for source-qualified incident sequences, retained domain history, platform-object continuity, authorised storefront
|
|
232
300
|
comparison and connector provenance. These workflows are offline; partial
|
|
233
301
|
context reviews return 4 when `--strict-exit` is selected. Browser-generated
|
|
234
302
|
reusable inputs use the same validators.
|
|
235
303
|
|
|
304
|
+
Domain-history input version 2 adds analyst-declared registration, deletion,
|
|
305
|
+
re-registration, transfer or review boundaries linked to retained snapshot or
|
|
306
|
+
pin IDs. Version 1 remains supported with its original output. Boundaries prompt
|
|
307
|
+
reassessment; they do not establish ownership or discard prior evidence.
|
|
308
|
+
|
|
309
|
+
`review-evidence containment.json --json --strict-exit` accepts a
|
|
310
|
+
`whoisleuth.internal-containment.input` version-1 document containing a supported
|
|
311
|
+
case export, selected next-step assertion and linked pin IDs, internal or trusted
|
|
312
|
+
audience, recipient role and an explicit disclosure-review acknowledgement.
|
|
313
|
+
It exports only that selected handoff, never writes the case or performs a
|
|
314
|
+
control. Missing or unselected supporting context stays partial (exit 4 under
|
|
315
|
+
`--strict-exit`), and a resolved case or provider outcome does not close an open
|
|
316
|
+
internal follow-up. See [internal containment](offline-intake-context.md#selected-internal-containment-handoff)
|
|
317
|
+
for the complete input and audience limitations.
|
|
318
|
+
|
|
236
319
|
### Message-header review
|
|
237
320
|
|
|
238
321
|
`mail-headers` parses only the bounded header block from a selected message file
|
|
@@ -282,9 +365,48 @@ selected file, including an envelope when supplied. No provider API is contacted
|
|
|
282
365
|
|
|
283
366
|
## Output and automation
|
|
284
367
|
|
|
285
|
-
### Local
|
|
286
|
-
|
|
287
|
-
|
|
368
|
+
### Local case files
|
|
369
|
+
|
|
370
|
+
Manual response scope is explicit and offline. `case incident-link` takes
|
|
371
|
+
`{"url":"https://example.test/reported-page"}`; use its retained ID to bind
|
|
372
|
+
`responseObjects` on `case action`. Each object contains `kind`, `identifier`
|
|
373
|
+
and `incidentTargetId` (null for the case domain or an associated hostname).
|
|
374
|
+
New URL objects must match that exact retained link. Exact historical identities
|
|
375
|
+
already retained in response records remain selectable after a link edit or
|
|
376
|
+
removal; they are not rebound to its replacement. An action may bind up to 20
|
|
377
|
+
objects; missing historical scope stays unknown.
|
|
378
|
+
|
|
379
|
+
`case action-event` takes `{"id":"action-id","transition":{...}}`, using
|
|
380
|
+
the same reviewed, authorised and manually submitted workflow as the console.
|
|
381
|
+
After submission, a typed `objectOutcome` such as `removed`, `restricted`,
|
|
382
|
+
`suspended`, `delisted`, `restored` or `disputed` requires explicit event
|
|
383
|
+
`responseObjects`: a partial receipt never applies to all objects by default.
|
|
384
|
+
Acknowledgement is a workflow event, not independently observed remediation.
|
|
385
|
+
|
|
386
|
+
A self-initiated correction uses a new `case action`, with `originActionId`
|
|
387
|
+
identifying the original action and `responseObjects` selecting a subset of that
|
|
388
|
+
delivery's exact objects. Its `correction` block identifies one delivery event,
|
|
389
|
+
packet digest/version and profile, plus the purpose (`correction` or
|
|
390
|
+
`retraction_request`), reason, previous and corrected statements, and retained
|
|
391
|
+
evidence-pin IDs. This is separate from `amendment`, which still requires an
|
|
392
|
+
actual provider-request event. The correction must match a retained typed packet
|
|
393
|
+
receipt on the selected delivery; a historical free-text digest alone is
|
|
394
|
+
insufficient. The usual recipient, authority and disclosure review then applies
|
|
395
|
+
to the new draft. The original packet and delivery remain unchanged.
|
|
396
|
+
|
|
397
|
+
`case recheck-question` saves `statement` and `recheck` comparison conditions.
|
|
398
|
+
Pins, questions and recheck input can retain one `responseObject`; exact-object
|
|
399
|
+
non-reproduction requires matching complete baseline/current evidence, a later
|
|
400
|
+
observation and comparable conditions. Hostname similarity is insufficient.
|
|
401
|
+
Independent removal, restriction, suspension, delisting, transfer and restoration
|
|
402
|
+
use those same comparison requirements. Disputes and warnings retain procedural
|
|
403
|
+
source attribution separately; provider claims are not independent observations.
|
|
404
|
+
`case close-object` requires one `responseObject` and the usual typed closure
|
|
405
|
+
reason/evidence links. It leaves the case and other objects unchanged.
|
|
406
|
+
All these JSON operations require `--input`, `--output`, deliberate file
|
|
407
|
+
replacement and the existing digest/lease checks. No report or request is sent.
|
|
408
|
+
|
|
409
|
+
Create a working file, inspect its case IDs, then append a note:
|
|
288
410
|
|
|
289
411
|
```sh
|
|
290
412
|
whoisleuth case open --domain example.test --title "Review the selected form" --output cases.json
|
|
@@ -292,8 +414,8 @@ whoisleuth case show cases.json
|
|
|
292
414
|
whoisleuth case note cases.json --note-file note.txt --output cases.json --force
|
|
293
415
|
```
|
|
294
416
|
|
|
295
|
-
Use `--case-id` when the file contains several
|
|
296
|
-
|
|
417
|
+
Use `--case-id` when the file contains several cases. `open` reuses the selected
|
|
418
|
+
case; `--new-incident --title "Another incident"` creates a distinct ID for the
|
|
297
419
|
same domain. It does not open a browser or collect anything.
|
|
298
420
|
|
|
299
421
|
`pin`, `link`, `withdraw-link`, `assess` and `recheck` read a selected JSON file with `--input`:
|
|
@@ -350,23 +472,23 @@ A recheck input contains `state`, `observedAt`, `completeness`, `source` and
|
|
|
350
472
|
`comparisonSummary`, with optional limitations and follow-up time. For example,
|
|
351
473
|
use `state: "unavailable"` and `completeness: "partial"` when a supplied capture
|
|
352
474
|
did not complete. `not_reproduced` requires a saved recheck question from the
|
|
353
|
-
|
|
475
|
+
case's console workflow, its exact `recheck` context, the target
|
|
354
476
|
`observationHostname`, a complete later observation where a baseline exists,
|
|
355
477
|
and `conditionsMatch: "comparable"`. It never means global removal or takedown.
|
|
356
478
|
|
|
357
|
-
Mutations require an explicit output path and write the complete current
|
|
479
|
+
Mutations require an explicit output path and write the complete current case
|
|
358
480
|
export. They never prune old evidence to fit. Input formatting may use up to
|
|
359
|
-
16 MiB; the canonical store remains limited to 4 MiB and 500
|
|
360
|
-
can export a selected subset to a **different** path. Ordinary
|
|
481
|
+
16 MiB; the canonical store remains limited to 4 MiB and 500 cases. `show --json`
|
|
482
|
+
can export a selected subset to a **different** path. Ordinary case imports also
|
|
361
483
|
allow 16 MiB for formatting and export metadata; the stored-data limit remains
|
|
362
|
-
4 MiB. Case packs retain their separate 25-
|
|
484
|
+
4 MiB. Case packs retain their separate 25-case selection and 4-MiB source-file
|
|
363
485
|
limits, and include generated reports within the bounded import allowance.
|
|
364
486
|
|
|
365
487
|
`show` reports the exact file digest. Add `--expect-file-digest sha256:<digest>`
|
|
366
488
|
to reject a file changed since that review. Source/output locks and atomic
|
|
367
489
|
replacement also detect changes during execution. After an interrupted process,
|
|
368
490
|
inspect its adjacent `.workflow.lock` before deliberately removing it. Validation
|
|
369
|
-
or conflict failures leave the
|
|
491
|
+
or conflict failures leave the case file unchanged and return 2. Filesystem
|
|
370
492
|
publication failures return 3.
|
|
371
493
|
|
|
372
494
|
Working files contain private analyst content and file references, not attachment
|
|
@@ -386,21 +508,26 @@ whoisleuth manifest evidence.json screenshot.png --workflow "Evidence review" \
|
|
|
386
508
|
whoisleuth verify-artifact --folder ./evidence-project --json --strict-exit
|
|
387
509
|
```
|
|
388
510
|
|
|
389
|
-
Packages admit the 128-file, 64-MiB original selection plus one bounded
|
|
511
|
+
Packages admit the 128-file, 64-MiB original selection plus one bounded case
|
|
390
512
|
export, with a separate manifest allowance. Original-file limits remain unchanged.
|
|
391
|
-
`verify-artifact` uses the same exact ordinary
|
|
513
|
+
`verify-artifact` uses the same exact ordinary case reader as `case show`,
|
|
392
514
|
without repairing content. Package verification also reports original-reference
|
|
393
|
-
completeness for each
|
|
394
|
-
An ordinary
|
|
515
|
+
completeness for each case file; `--strict-exit` returns 4 when a referenced original is missing.
|
|
516
|
+
An ordinary case JSON file alone provides structural validity, not a checksum.
|
|
395
517
|
They use generated entry names, not original paths. Ordinary ZIPs and folders
|
|
396
518
|
are private and unencrypted; packaging does not redact selected files. The report distinguishes
|
|
397
519
|
file identity, supported source formats, opaque content, exact capsule/source
|
|
398
|
-
links and capture-manifest attachment matches.
|
|
520
|
+
links, declared image derivation and capture-manifest attachment matches.
|
|
521
|
+
Image derivation reports an immediate-parent digest and byte length, editing
|
|
522
|
+
method and operation kinds, not proof of transformation. Parent inclusion matches
|
|
523
|
+
another selected manifest entry by exact byte digest and size; an unselected case
|
|
524
|
+
attachment reference does not count. Parent pixels are optional; absent declarations
|
|
525
|
+
leave editing history unknown. Include the capture manifest and
|
|
399
526
|
its screenshot/DOM-digest files together to check their declared bytes; original
|
|
400
527
|
filenames are not needed to establish a match. It does not import files or establish source truth, signature trust or a
|
|
401
528
|
trusted timestamp. Unsupported or rejected entries produce a partial report;
|
|
402
529
|
`--strict-exit` returns 4. Without `--package` or `--folder`, `manifest` produces a
|
|
403
|
-
standalone JSON manifest; exact
|
|
530
|
+
standalone JSON manifest; exact version-2 and version-3 manifests remain readable.
|
|
404
531
|
|
|
405
532
|
For [BagIt 1.0](https://www.rfc-editor.org/rfc/rfc8493.html) interchange, use
|
|
406
533
|
`--bagit` with `--package` or `--folder` on both commands:
|
|
@@ -454,6 +581,35 @@ trees and unlisted files. Its package digest and byte count describe the
|
|
|
454
581
|
canonical stored-ZIP representation, not filesystem metadata. These are
|
|
455
582
|
selected evidence exports, not complete workspace backups.
|
|
456
583
|
|
|
584
|
+
### Exporting a fixed workflow for review
|
|
585
|
+
|
|
586
|
+
Terminal plans and recipe explanations distinguish networked steps, offline
|
|
587
|
+
steps and declared reuse of earlier outputs. These are step and handoff counts,
|
|
588
|
+
not request totals or confirmation that a saved file is available. The planner
|
|
589
|
+
does not inspect files or caches; collection and evidence selection remain
|
|
590
|
+
deliberate actions. JSON exports keep their existing versioned fields.
|
|
591
|
+
|
|
592
|
+
Select one installed recipe and save its declared steps for review:
|
|
593
|
+
|
|
594
|
+
```sh
|
|
595
|
+
whoisleuth workflow-plan --explain domain-triage --json --output recipe.json
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
The document includes the subject requirement, command and argument examples,
|
|
599
|
+
network modes, required approvals, output artefact families and completion guidance.
|
|
600
|
+
To prepare the same recipe for a specific subject:
|
|
601
|
+
|
|
602
|
+
```sh
|
|
603
|
+
whoisleuth workflow-plan domain-triage example.test --json --output plan.json
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
Both commands plan offline. The files contain declarative steps rather than
|
|
607
|
+
shell history or executable scripts. Argument examples and approval fields
|
|
608
|
+
describe requirements; they do not record a completed review or grant approval.
|
|
609
|
+
These are review documents, not `workflow-run` checkpoints or custom recipe
|
|
610
|
+
imports. Run an installed recipe deliberately with its required inputs and
|
|
611
|
+
fresh approvals.
|
|
612
|
+
|
|
457
613
|
### Resuming a fixed workflow
|
|
458
614
|
|
|
459
615
|
Inspect a paused run without executing any step or rewriting its checkpoint:
|
|
@@ -486,7 +642,7 @@ whoisleuth workflow-run domain-triage example.test --approve-network \
|
|
|
486
642
|
```
|
|
487
643
|
|
|
488
644
|
Bindings accept Lookup outputs for export, diff, timeline, comparison, source
|
|
489
|
-
reports and briefs; evidence exports for verification; and
|
|
645
|
+
reports and briefs; evidence exports for verification; and case-pack output
|
|
490
646
|
for sharing review. Remaining placeholders use `--select` in order;
|
|
491
647
|
for example, `--select diff=previous.json` keeps the current observation as the
|
|
492
648
|
second input. Supply every input for an uncompleted step to use files instead,
|
|
@@ -601,6 +757,9 @@ and machine output contains no ANSI or transient progress text.
|
|
|
601
757
|
- `lookup --browse` provides an interactive terminal view; press `?` for keys.
|
|
602
758
|
- `--events` writes versioned lifecycle events to stderr.
|
|
603
759
|
- `--strict-exit` and `--fail-on` expose selected evidence states to automation.
|
|
760
|
+
- `lookup --junit` reports retained diagnostic source states, not version or
|
|
761
|
+
timing metadata. Nested diagnostic failures remain failures; target-bearing
|
|
762
|
+
diagnostic paths are not copied into the XML. This is not a truth verdict.
|
|
604
763
|
- `--output` writes a private local file atomically and refuses an existing path
|
|
605
764
|
unless `--force` is also selected.
|
|
606
765
|
|
|
@@ -611,7 +770,22 @@ options override profile defaults.
|
|
|
611
770
|
|
|
612
771
|
`source-report` summarises collector-owned health envelopes in saved Lookup
|
|
613
772
|
and Bulk output. Raw publications and extension fields are not interpreted as
|
|
614
|
-
diagnostics, and missing health metadata remains unmeasured.
|
|
773
|
+
diagnostics, and missing health metadata remains unmeasured. Its text view groups
|
|
774
|
+
collection states, sample counts and durations under each source. Observation
|
|
775
|
+
durations and Lookup timings stay separate; merged-report distributions describe
|
|
776
|
+
retained report statistics, not a new measurement of individual requests.
|
|
777
|
+
|
|
778
|
+
After verifying a domain-control or Lookup-claim passport, `verify-artifact`
|
|
779
|
+
suggests the compatible offline `interchange-report` command. Suggestions use
|
|
780
|
+
example filenames and never run automatically. Other artefact families receive
|
|
781
|
+
guidance only when the suggested reader supports that format.
|
|
782
|
+
|
|
783
|
+
The text output of `brief` groups selected facts in an indented source tree.
|
|
784
|
+
Each source keeps its collection state and observation time, including sources
|
|
785
|
+
with no fact selected for the brief; that does not mean the source was empty.
|
|
786
|
+
Conflicting values remain separate and include both the value state and source
|
|
787
|
+
state. The brief uses retained evidence only. Use `--json` for the
|
|
788
|
+
structured report, including its facts, source health, unknowns and action plan.
|
|
615
789
|
|
|
616
790
|
`mail-review` keeps failed input targets, incomplete DNS coverage and original
|
|
617
791
|
collection times visible. Source-output and review-generation times do not
|