whodis

package module
v2.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 43 Imported by: 0

README

Whodis logo

whodis

A full, evidence-backed domain investigation suite.
Find out who operates a domain and what is behind it: registration, DNS, infrastructure, diagnostics, web technology, related domains, and changes over time.

Build status Latest release Release downloads MIT license Linux, macOS, and Windows

Homepage · Download · Install · Quick start · Issues

One engine. Use it your way.

Whodis terminal dashboard showing an automatic RDAP lookup for cyberbrand.netWhodis native desktop registration view for cyberbrand.net
Terminal Native desktop
Fast in shells, scripts, SSH sessions, and servers. Native controls on Linux, Windows, and macOS.

whodis cyberbrand.net discovers the authoritative source automatically and turns the result into a readable terminal workspace. The separately packaged desktop application presents the same normalized investigation engine through focused native views. Start with the original question; go deeper when you need the whole story.

One target. The answer you need

Whodis accepts a domain, IP address, network, or ASN. Registration identity is the effortless default; focused operations add DNS, service health, infrastructure attribution, technology evidence, research pivots, and change tracking without making the simple lookup complicated.

Question Command What Whodis shows
Who manages it? whodis cyberbrand.net Authoritative RDAP, WHOIS, or RWhois registration, status, dates, contacts, and nameservers
What is published? whodis inspect cyberbrand.net Registration plus a practical public-DNS inventory
Is it configured and reachable? whodis diagnose cyberbrand.net DNS, delegation, web, TLS, mail, and advertised-service findings
What is behind the site? whodis investigate cyberbrand.net Hosting and network attribution, technology stack, homepage observations, research links, and evidence
What changed or needs attention? whodis diff … / whodis check … Semantic changes and deterministic policy results for automation or monitoring

A full domain investigation suite

  • Registration and identity: Route domains, IPs, networks, and ASNs to the right IANA-published RDAP authority, fall back to WHOIS when appropriate, and follow RWhois referrals without making users learn the protocol map.
  • DNS and delegation: Inventory records, query arbitrary types, compare resolvers, validate DNSSEC, trace delegation from the root, and perform explicit bounded zone transfers.
  • Infrastructure and service diagnostics: Connect public DNS to network ownership, hosting signals, HTTP, TLS, SMTP, mail policy, reachability, and advertised services with scoped findings instead of an opaque score.
  • Website technology investigation: Identify platforms, versions, WordPress plugins and themes, commerce, optimization, server and edge technology, and homepage delivery signals with confidence and inspectable evidence.
  • Research and relationships: Generate curated manual pivots for public sources and, only when requested, add bounded AlienVault OTX passive-DNS observations without presenting historical neighbors as ownership claims.
  • Change tracking and automation: Save sanitized observations, compare meaningful changes, enforce policy, process large batches, and export a stable report for scripts and other applications.

Built for terminals, desktops, and automation

  • Responsive terminal dashboard: A spreadsheet-like panel grid uses the available width without repeating contacts, notices, or nameservers.
  • Multiple layouts: Dashboard, semantic tree, retro GeekBoys ASCII, and portable plain text are one switch away.
  • Structured output: Versioned JSON/YAML, one-row-per-target CSV, and streaming-friendly NDJSON support automation; Markdown makes a portable report.
  • Focused batch tables: Check many targets, select fields such as expiration and registrar, and write directly to a file.
  • Raw source access: Preserve the original RDAP JSON, WHOIS, or RWhois response when one unmodified registration lookup is what you need.
  • Native desktop workbench: Lookup, DNS Inventory, DNS Query, Compare, Delegation, Diagnose, Stack, Research, Related, Services, Findings, Contacts, and Raw views without a browser or a separately installed CLI. Result columns are adjustable and remembered per view, while long values wrap instead of being clipped or forcing the whole layout sideways.
  • Help where you work: Concise guides ship inside both applications. Use whodis help [topic] in a terminal or press F1 in the desktop app; neither requires a browser or network connection.
  • Evidence-backed site profile: Identify platforms, versions, WordPress plugins and themes, commerce, optimization, hosting, DNS, and mail, then review a score-free homepage delivery, SEO, security-header, and accessibility snapshot.
Whodis semantic tree output for palantir.comWhodis GeekBoys ASCII output for geekboys.org
Semantic tree GeekBoys retro ASCII

Native desktop when you want it

The CLI stays small for shells, scripts, SSH sessions, and servers. The separately packaged native desktop application exposes the same engine through focused registration, DNS, diagnosis, investigation, research, findings, batch, and raw-data views. The registration view appears beside the terminal at the top of this page; the examples below show deeper desktop workflows.

Whodis DNS query showing A and AAAA records for cyberbrand.netWhodis diagnosis showing DNS, web, TLS, mail, and policy findings for cyberbrand.net
DNS query Domain diagnosis

Concurrent batch lookup · Check and export many domains in one run

Whodis batch lookup showing four completed domain checks

The GUI and every terminal renderer consume the same normalized report. Long registry notices are deduplicated and summarized; --details expands them.

Install

Whodis releases two independent applications from one codebase:

  • whodis is the small CLI for shells, scripts, SSH sessions, and servers.
  • whodis-gui is the native desktop app. It bundles a private Whodis engine and does not require the CLI on PATH.

Linux and macOS CLI

curl -fsSL https://github.com/Alex9001/whodis/releases/latest/download/install.sh | sh

The installer detects the operating system and CPU, verifies SHA-256 against the release checksums, and installs whodis into /usr/local/bin. It asks for sudo only when the destination is not writable.

Windows CLI

Run this in PowerShell; an administrator window is not required:

irm https://github.com/Alex9001/whodis/releases/latest/download/install.ps1 | iex

The installer verifies the archive, installs under local application data, and adds the directory to the user PATH. Open a new terminal and type whodis.

Go, archives, and Arch Linux

go install github.com/Alex9001/whodis/v2/cmd/whodis@latest

Prebuilt CLI archives are published for Linux, macOS, Windows, FreeBSD, and OpenBSD on amd64 and supported arm64 targets. Source-built AUR definitions for whodis and whodis-gui are ready; the maintainer's one-time account and key steps are in the AUR publication guide.

Each release also carries installable .deb, .rpm, Alpine Linux .apk, and Arch Linux packages. An optional non-root multi-architecture container is published to GitHub Container Registry:

docker run --rm ghcr.io/alex9001/whodis example.com

Checksum-pinned Homebrew, Scoop, and Nix manifest generation is ready for package-channel publication; see the community package guide. The README does not claim a channel is live until its upstream page exists.

Desktop app

Download whodis-gui from the latest GitHub Release:

  • Linux: run the amd64 or arm64 AppImage.
  • Windows: use the per-user setup executable or portable ZIP.
  • macOS: open the universal DMG and drag Whodis into Applications.

Desktop packages are not code-signed or notarized. Windows SmartScreen and macOS Gatekeeper will warn on first launch. Verify the published SHA-256 checksum or GitHub build attestation, then use More info → Run anyway on Windows or Open Anyway in macOS Privacy & Security settings.

Quick start

Registration stays effortless:

whodis google.com
whodis 8.8.8.8
whodis AS15169

Ask for the operation you want when you need more:

# Registration plus a practical public-DNS inventory, including MX
whodis inspect example.com

# DNS inventory without registration data
whodis dns inventory example.com

# Arbitrary DNS types or numeric TYPE values
whodis dns query example.com A AAAA MX HTTPS TYPE257

# Compare normalized answers from recursive and authoritative resolvers
whodis dns compare example.com A

# Follow delegation iteratively from a root server
whodis dns trace example.com NS

# Bounded DNS, reachability, HTTP, TLS, SMTP, and mail-policy checks
whodis diagnose example.com

# Explainable technology, provider, and network attribution from public evidence
whodis investigate example.com

# Explicitly add OTX passive-DNS history and live-check returned hostnames
WHODIS_OTX_API_KEY=... whodis investigate example.com --enrich otx

# Save a passive observation, compare it later, and enforce health policy
whodis inspect example.com --save --label production
whodis diff production --live
whodis check example.com --scrutiny strict

Help is built in

Run whodis help to see command reference and the bundled guide catalog, then open a focused topic such as whodis help registration, whodis help dns, whodis help investigate, whodis help snapshots, or whodis help troubleshooting. The native app exposes the same searchable guides through Help → Whodis Help or F1, alongside links to the homepage, full online documentation, and issue tracker.

The bundled material is intentionally concise and task-oriented. This README remains the complete installation, architecture, safety, and limitation reference, so command help does not become a stale second manual.

A full DNS client, not a decorative lookup

whodis dns query accepts named or numeric record types and classes. Resolver URIs select the transport explicitly:

Resolver form Transport
system, 1.1.1.1, udp://1.1.1.1 UDP with automatic TCP retry on truncation
tcp://1.1.1.1 DNS over TCP
tls://dns.example or dot://… DNS over TLS
https://…/dns-query DNS over HTTPS
h3://…/dns-query DNS over HTTP/3
doq://dns.example DNS over QUIC
sdns://… DNSCrypt stamp

Responses retain header flags, timing, transport, resolver identity, answer, authority, additional records, raw wire bytes, EDNS Extended DNS Errors, and a DNSSEC state. EDNS controls include buffer size, DO, NSID, explicit ECS, cookie, padding, checking-disabled, and recursion behavior.

whodis dns query example.com MX TXT --resolver tls://dns.quad9.net --dnssec

whodis dns compare example.com A \
  --resolver https://cloudflare-dns.com/dns-query \
  --resolver tls://dns.google \
  --strategy consensus

whodis dns transfer example.com --ixfr --serial 12345 --tls

Compare ignores TTL and answer order when deciding whether resolvers disagree. Trace follows referrals from embedded root hints and reports glue, missing glue, lame delegation, and DNSSEC delegation state. AXFR and IXFR are always explicit, bounded by a record safety limit, and support TSIG and TLS.

With --dnssec, Whodis locally verifies positive signed answer RRsets and their DNSKEY/DS chain against embedded IANA root trust anchors. It reports secure, insecure, bogus, or indeterminate rather than blindly trusting a resolver's AD bit.

Optional worldwide DNS views

Globalping is strictly opt-in because it sends the target and location request to a third-party service and may consume API quota:

whodis dns query example.com A --globalping --from US --from Europe --limit 3
whodis diagnose example.com --remote

Set GLOBALPING_TOKEN when using authenticated quota. Whodis has no telemetry, account system, or background network activity of its own.

Diagnose without becoming a port scanner

whodis diagnose uses only endpoints derived from the target and its published configuration. Work is time-bounded and capped:

  • DNS inventory with local DNSSEC validation and iterative delegation tracing
  • representative IPv4 and IPv6 reachability
  • apex and www HTTP/HTTPS status and redirect chains
  • TLS identity, certificate dates, cipher, version, and ALPN
  • sampled MX SMTP greeting, EHLO capabilities, STARTTLS, and TLS verification
  • SPF, DMARC, MTA-STS, and TLS-RPT discovery, plus MTA-STS policy retrieval
  • DNS-advertised SRV, SVCB, and HTTPS service endpoints
  • optional local path trace with --trace

Findings are deterministic pass, info, warning, or error observations with evidence. There is deliberately no opaque overall score and no arbitrary port-range scanner.

Investigate a site's stack without hand-waving

whodis investigate builds on Diagnose and turns bounded public observations into a quick, renderer-independent stack profile. It combines one homepage HTTP response, DNS provider patterns, mail records, PTR names, and IP RDAP registration. Web fingerprints use the MIT-licensed wappalyzergo engine, augmented with conservative header, cookie-name, generator, asset-path, and markup signals.

whodis investigate example.com
whodis investigate example.com --markdown -o profile.md
whodis investigate example.com --research-links all
whodis investigate example.com --enrich otx --related-limit 50 --json

Each detected component has a category, role, optional version and parent, descriptive traits, high/medium/low confidence, the basis for that confidence, and bounded evidence behind it. Known WordPress paths identify products such as WooCommerce, Gravity Forms, Ninja Forms, ACF, Elementor, Genesis, and common cache/optimization plugins. Unknown public plugin or theme slugs are preserved as explicitly unmapped observations instead of being silently discarded. Whodis deliberately separates a network owner such as Amazon from a managed hosting provider, and does not call a lone autodiscover record Microsoft 365 or cPanel. A compact summary is followed by evidence tables in terminal output. In the desktop app, the Overview immediately summarizes the web platform, commerce, plugins/forms, theme, optimization, server/edge, hosting, network, DNS, mail, and homepage observations. Homepage observations cover response delivery and source-level asset hints, basic metadata, browser security headers, and a few static accessibility markers. Their deterministic pass/info/warning entries appear in the existing Findings view; there is no synthetic score. The Stack view uses a clean master/detail layout: select one technology, network, or note to see its wrapped summary and evidence below, without repetitive evidence rows. The dedicated Research view keeps manual third-party pivots out of the evidence tree, grouped under the domain and each public IP. The Related view keeps passive observations separate from stack claims.

Local investigation is the default. It reads at most the first 1 MiB of the single final homepage response. It does not execute JavaScript, fetch referenced assets, crawl additional pages, calculate Lighthouse/Core Web Vitals, assign a site grade, scan arbitrary ports, or contact related domains. A missing signal means only “not observed in this bounded response.” It is not proof that a product is absent or that a security issue exists. Whodis locally creates a curated set of links for AlienVault OTX, VirusTotal, BuiltWith, urlscan.io, crt.sh, the Wayback Machine, Shodan, and Censys. It does not contact those services until you explicitly open a link. Additional Wappalyzer, Netcraft, GreyNoise, AbuseIPDB, BGP.Tools, and IPinfo links are available with --research-links all; use off or a comma-separated provider list for an exact selection. Some services may require their own account or impose their own usage limits.

Research links are separate from enrichment. OTX passive-DNS enrichment happens only with --enrich otx; discovered public web IPs are sent to that service, returned observations are capped, and their hostnames are checked against current A/AAAA DNS. current, stale, and unknown describe that DNS comparison. They do not establish ownership or affiliation.

The optional OTX key comes only from WHODIS_OTX_API_KEY and is never written to Whodis configuration, reports, snapshots, or logs. Customize harmless defaults with whodis config set related-limit, research-links, investigation-link, and otx-endpoint. investigation-link remains an optional custom HTTPS template containing {type} and {value}. Enrichment opt-in itself is never persisted.

Snapshots, change detection, and policy checks

Eligible local observations can be saved as snapshots. Dedicated API-token and TSIG-secret fields, raw DNS packets, request IDs, and timings are removed before storage. Local investigation reports can be saved; runs using third-party enrichment cannot:

whodis inspect example.com --save --label production
whodis snapshot list
whodis snapshot show production
whodis diff production --live

For safety, a live replay does not activate custom registry servers or DNS resolver endpoints stored in an imported snapshot. If you created and trust the snapshot, opt in explicitly with whodis diff production --live --allow-snapshot-endpoints.

Diffs are semantic and deterministic: record ordering and TTL churn are ignored unless --include-ttl is requested. A provider failure makes its section uncertain instead of manufacturing a removal. Exit status 5 means material changes were found; 6 means the comparison was incomplete.

whodis check turns the same reports into CI- and monitoring-friendly policy results:

whodis check example.com
whodis check example.com --active --scrutiny strict
whodis check example.com --against production --policy whodis-policy.yaml --json
whodis check --snapshot production

The built-in basic, standard, and strict scrutiny levels cover registration expiry, nameservers, DNSSEC, diagnostic findings, and TLS expiry. Strict YAML/JSON policies can require registration states, DNS records, nameservers, MX values, DNSSEC state, certificate lifetime, or allowed diff paths. Optional webhooks are sent only for failed or unknown checks; their URL can be read from an environment variable or file to keep it out of shell history. Start with examples/whodis-policy.yaml. Snapshots never run in the background.

Batch checks and files

Most registration and workstation commands accept several targets and preserve input order while using bounded concurrency:

whodis expires google.com yahoo.com
whodis get expiration,registrar,status -i domains.txt -o results.txt
whodis diagnose example.com example.net --ndjson -o diagnosis.ndjson
printf 'google.com\nyahoo.com\n' | whodis expires

Use --jobs 1 through --jobs 32 to control concurrency. Individual failures remain attributed to their input and do not erase successful results. Existing files are protected unless --force is supplied. .json, .ndjson, .csv, .yaml, .md, and .txt output names select their formats automatically. Use -f/--format when an extension should not decide. check and diff support plain text, JSON, YAML, and Markdown through the same file rules.

Choose defaults once

Run the interactive wizard:

whodis config

Whodis interactive configuration wizard showing output format and color choices

It configures output layout, color, notice detail, DNS resolver and DNSSEC defaults, the manual research-link preset and related-result limit, plus the scrutiny and passive/active mode used by whodis check. Press Enter to retain a choice or review everything before saving. Direct commands are available for automation:

whodis config set format tree
whodis config set resolver 'https://cloudflare-dns.com/dns-query'
whodis config set strategy consensus
whodis config set dnssec on
whodis config set scrutiny strict
whodis config set check-mode passive
whodis config set related-limit 50
whodis config set investigation-link 'https://otx.alienvault.com/indicator/{type}/{value}'
whodis config get resolver
whodis config reset

Command-line options always override saved defaults; --no-dnssec provides an explicit one-run override. Generate shell completion with whodis completion bash|zsh|fish|powershell.

Command shape

whodis <target>
whodis registration <target...>
whodis inspect <domain...>
whodis dns query <name> [TYPE...]
whodis dns inventory <domain...>
whodis dns compare <name> [TYPE...]
whodis dns trace <name> [TYPE]
whodis dns transfer <zone>
whodis diagnose <domain...>
whodis investigate <domain...>
whodis check <target...>
whodis snapshot <list|show|remove|export|import|path> ...
whodis diff <snapshot> <snapshot>|--live
whodis expires <target...>
whodis get <fields> <target...>

Add -f dashboard|tree|geekboys|plain|json|yaml|csv|ndjson|markdown|raw to select output (the equivalent long shortcuts also work). whodis help dns, whodis help diagnose, whodis help investigate, and whodis help advanced document operation-specific controls; whodis help also lists offline guides for workflows and troubleshooting. The older scan and axfr spellings remain available for compatibility.

How registration routing works

Whodis caches IANA's RDAP bootstrap registries for domains, IPv4, IPv6, and ASNs. Domain routes use the longest registry suffix; IP routes use the longest network prefix; ASN routes use the published number ranges. HTTPS endpoints are preferred and alternate endpoints are tried before changing protocol.

When no RDAP service is published, Whodis asks whois.iana.org for the authoritative WHOIS server and follows a bounded referral chain. It follows a published rwhois:// referral automatically. A direct authority can be forced with whodis rdap|whois|rwhois ... --server; RWhois direct mode requires the server because no global RWhois bootstrap exists.

Automatic routing falls back only for an unavailable or unusable service. Authoritative not-found and rate-limit responses remain visible. --try-both widens diagnostic fallback and --strict disables it.

Automatically discovered RDAP URLs require HTTPS, and automatic RDAP, WHOIS, and RWhois referrals to private, loopback, link-local, documentation, or other special-use addresses are blocked. Diagnose and Investigate apply the same rule to target-derived web, TLS, SMTP, MTA-STS, and advertised-service destinations, including every HTTP redirect. Explicitly managed internal infrastructure can opt in per run with --allow-private; automatic HTTP RDAP requires the separate --allow-insecure-http exception.

Go SDK and report schema

The supported public API is renderer-independent. The CLI and GUI both call the same concurrency-safe Engine and provider boundaries:

engine := whodis.NewEngine(whodis.EngineOptions{})
report, err := engine.Run(ctx, whodis.Request{
    Operation: whodis.OperationDNSQuery,
    Target:    "example.com",
    DNS:       whodis.DNSOptions{Types: []string{"A", "AAAA", "MX"}},
})
err = whodis.RenderReport(os.Stdout, report, whodis.FormatJSON, whodis.RenderOptions{})

Report schema version 5 keeps registration, DNS, diagnosis, investigation, findings, and provider-scoped errors independent, so one failed registry, probe, or enrichment does not erase useful results. Schema v5 adds explainable stack components, a bounded homepage profile, network attribution, curated manual research links, and bounded related observations. Snapshot replay continues to read schema-v4 snapshots. Diagnostic findings are aggregated once at report level instead of being duplicated inside the diagnosis payload. Engine.RunBatch preserves input order, while Engine.RunStream handles input incrementally with bounded work and progress callbacks. Registration, DNS, Diagnose, Investigation, and named Enrichment providers are interfaces for embedding and deterministic tests. EngineLimits independently bounds batch size, registration lookups, and nested diagnostic probes for long-lived or multi-tenant integrations. Engine instances share the immutable compiled web fingerprint catalog, so repeatedly constructing an embedded engine does not rebuild that large dataset.

The native GUI's private newline-delimited JSON-RPC protocol is version 5 and carries schema-v5 reports through the same operation engine as the CLI, plus progress, cancellation, the research-provider catalog, short-lived in-memory result tokens, and exports. See MIGRATING_TO_V2.md when upgrading an embedded v1 client.

Development and release integrity

git clone https://github.com/Alex9001/whodis.git
cd whodis
go test -race ./...
go vet ./...
go test ./... -run '^$' -bench . -benchtime=100ms
go run ./cmd/whodis example.com

The desktop build additionally needs CMake, Ninja, Qt 6 Core/Gui/Widgets/Test, and a C++17 compiler; source builds require Go 1.25 or newer. See desktop/README.md. Tests use fixtures and in-memory protocol sessions rather than consuming public registry or Globalping quota. Parser, importer, and renderer fuzz targets run on a monthly maintenance workflow; its public-protocol compatibility job is manual and advisory so ordinary CI stays deterministic and offline.

Release automation has a non-publishing preflight that cross-builds the pure-Go CLI and every native desktop bundle before a tag is created. It runs race and vulnerability checks, generates staged-content SBOMs and SHA-256 checksums, attests the exact release bytes, and only then publishes them. Releases remain split into CLI and GUI assets so a server never needs to install Qt.

Boundaries and honest limitations

  • RWhois has no global bootstrap registry. Automatic discovery needs a published RDAP port43 hint or WHOIS ReferralServer; otherwise use an explicit rwhois --server authority.
  • DNS inventory checks a maintained set of practical owner names and record types; DNS has no universal record-list operation. Only a successful AXFR is a complete zone, and most public authoritative servers correctly refuse it.
  • Local DNSSEC validation currently validates positive signed answer chains. Authenticated denial proofs for NXDOMAIN/NODATA are reported as indeterminate rather than overstated as secure.
  • Path tracing can require operating-system ICMP permissions. Whodis reports a scoped warning when the host does not allow the native probe.
  • Diagnose samples bounded representative addresses, MX hosts, and advertised services. It is evidence collection, not continuous monitoring or an exhaustive security audit.
  • Technology fingerprints and provider mappings are evidence-backed best efforts, not contractual proof. Sites can hide, proxy, or spoof headers and infrastructure. The homepage audit is a static, single-response observation: it does not execute JavaScript, fetch assets, crawl pages, measure browser performance, claim that an unobserved plugin is absent, grade a site, or perform a vulnerability assessment. Passive-DNS neighbors are historical observations, not ownership, customer, or compromise claims.
  • Raw source output is limited to one registration response. Multi-target and workstation operations use human-readable or structured report formats.
  • The desktop batch workspace accepts up to 1,000 targets and retains recent exportable results in a bounded in-memory cache. Use CLI NDJSON streaming for larger jobs.
  • Saved snapshots are local files, not a scheduler or hosted monitoring service. Use cron, systemd timers, Task Scheduler, or CI to run checks.
  • Authenticated registry accounts, proprietary registry APIs, web scraping, generic port scanning, telemetry, mobile apps, and app-store distribution are intentionally out of scope.
  • Desktop packages are currently unsigned and distributed through GitHub Releases; SmartScreen and Gatekeeper may require a deliberate first launch.

License

MIT © 2026 Aleksandr Oreshkin. See LICENSE.

Documentation

Overview

Package whodis provides protocol-aware registration-data lookups.

Its public API intentionally has no terminal or GUI dependency, so the same Engine can power command-line, native desktop, and embedded clients.

Index

Constants

View Source
const ReportSchemaVersion = 5

ReportSchemaVersion is the version of Whodis's public JSON report schema.

Variables

This section is empty.

Functions

func ParseDNSName

func ParseDNSName(input string) (string, error)

ParseDNSName canonicalizes a general DNS owner name. Unlike ParseTarget it accepts service labels, wildcards, and the root zone.

func Render

func Render(writer io.Writer, result LookupResult, format Format, options RenderOptions) error

Render writes one successful result in the requested format.

func RenderBatch

func RenderBatch(writer io.Writer, batch BatchResult, format Format, options BatchRenderOptions) error

RenderBatch writes a completed batch. Empty Fields preserves complete registration results; non-empty Fields activates the compact projection.

func RenderBatchReport

func RenderBatchReport(writer io.Writer, batch BatchReport, format Format, options RenderOptions) error

RenderBatchReport writes schema-v5 reports in request order.

func RenderReport

func RenderReport(writer io.Writer, report Report, format Format, options RenderOptions) error

RenderReport writes one schema-v5 engine report. Registration-only reports retain the established Whodis layouts; workstation operations use compact, sectioned tables with the same output-format contract.

func ValidateDNSOptions

func ValidateDNSOptions(options DNSOptions) error

ValidateDNSOptions validates public DNS settings without performing network activity. It is useful to configuration UIs and SDK callers.

func ValidateInvestigationOptions added in v2.1.0

func ValidateInvestigationOptions(options InvestigationOptions) error

ValidateInvestigationOptions checks configuration that can be validated without contacting a provider. Engine execution additionally applies the configured network policy to custom endpoints.

Types

type AddressProbe

type AddressProbe struct {
	Address   string        `json:"address" yaml:"address"`
	Network   string        `json:"network" yaml:"network"`
	Method    string        `json:"method" yaml:"method"`
	Port      uint16        `json:"port,omitempty" yaml:"port,omitempty"`
	Reachable bool          `json:"reachable" yaml:"reachable"`
	Duration  time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Error     string        `json:"error,omitempty" yaml:"error,omitempty"`
}

AddressProbe captures one bounded reachability check.

type BatchError

type BatchError struct {
	Kind    ErrorKind `json:"kind" yaml:"kind"`
	Message string    `json:"message" yaml:"message"`
}

BatchError is the safe-to-serialize form of a lookup failure.

type BatchItem

type BatchItem struct {
	Input  string        `json:"input" yaml:"input"`
	Result *LookupResult `json:"result,omitempty" yaml:"result,omitempty"`
	Error  *BatchError   `json:"error,omitempty" yaml:"error,omitempty"`
}

BatchItem retains the original input so an invalid target and a successful canonicalized target can be displayed together without losing attribution. Exactly one of Result and Error is set after LookupBatch completes.

type BatchLookupOptions

type BatchLookupOptions struct {
	LookupOptions LookupOptions
	Workers       int
	// OnProgress is called once for each completed item. Calls are serialized
	// in completion order and never overlap. The callback may be nil.
	OnProgress func(BatchProgress)
}

BatchLookupOptions controls a concurrent group of independent lookups. Workers defaults to four when it is zero. Per-item lookup errors are returned in BatchResult rather than stopping the rest of the batch.

type BatchProgress

type BatchProgress struct {
	Index     int
	Completed int
	Total     int
	Item      BatchItem
}

BatchProgress describes one completed item in an active batch lookup. Index is the item's original input position, while Completed counts all items completed so far regardless of input order.

type BatchRenderOptions

type BatchRenderOptions struct {
	RenderOptions
	Fields []ProjectionField
}

BatchRenderOptions controls rendering of batch results. Fields selects the compact projection mode; an empty list renders complete lookup results.

type BatchReport

type BatchReport struct {
	SchemaVersion int      `json:"schema_version" yaml:"schema_version"`
	Reports       []Report `json:"reports" yaml:"reports"`
}

BatchReport preserves request order and partial failures.

type BatchRequest

type BatchRequest struct {
	Requests   []Request
	Workers    int
	OnProgress func(ProgressEvent)
}

BatchRequest controls a bounded group of independent engine requests.

type BatchResult

type BatchResult struct {
	SchemaVersion int         `json:"schema_version" yaml:"schema_version"`
	Items         []BatchItem `json:"items" yaml:"items"`
}

BatchResult is the serializable response returned by Client.LookupBatch. Embedded LookupResult values retain their own schema version.

func (BatchResult) HasErrors

func (r BatchResult) HasErrors() bool

HasErrors reports whether any item in the completed batch failed.

type Client deprecated

type Client struct {
	// contains filtered or unexported fields
}

Client is safe to reuse for multiple sequential or concurrent registration lookups.

Deprecated: use Engine for new integrations. Client remains available for source compatibility with registration-focused v1 callers.

func NewClient deprecated

func NewClient(options ClientOptions) *Client

NewClient creates a protocol-aware lookup client. It makes no network requests until Route or Lookup is called.

Deprecated: use NewEngine for new integrations.

func (*Client) Close

func (c *Client) Close() error

Close releases pooled network transports. It is safe to call repeatedly.

func (*Client) Lookup

func (c *Client) Lookup(ctx context.Context, input string, options LookupOptions) (LookupResult, error)

Lookup resolves one target and returns a stable, renderer-independent model.

func (*Client) LookupBatch

func (c *Client) LookupBatch(ctx context.Context, inputs []string, options BatchLookupOptions) (BatchResult, error)

LookupBatch resolves each input independently with bounded concurrency. It preserves order and duplicates, and records an error on the affected item rather than failing the entire operation.

func (*Client) Route

func (c *Client) Route(ctx context.Context, input string, options LookupOptions) (RouteDecision, error)

Route decides which known authority should receive a lookup without making a registration-data query. WHOIS route discovery may query IANA's referral service when the selected protocol is WHOIS.

type ClientOptions

type ClientOptions struct {
	Timeout        time.Duration
	CacheDirectory string
	Adapters       []ProtocolAdapter
	NetworkPolicy  NetworkPolicy
}

ClientOptions configures a reusable lookup client.

type Confidence added in v2.1.0

type Confidence string

Confidence describes the strength of an explainable investigation claim. It is deliberately categorical: callers should inspect Evidence rather than treating confidence as an opaque score.

const (
	ConfidenceHigh   Confidence = "high"
	ConfidenceMedium Confidence = "medium"
	ConfidenceLow    Confidence = "low"
)

type DNSDifference

type DNSDifference struct {
	Resolver string   `json:"resolver" yaml:"resolver"`
	Name     string   `json:"name,omitempty" yaml:"name,omitempty"`
	Type     string   `json:"type,omitempty" yaml:"type,omitempty"`
	Class    string   `json:"class,omitempty" yaml:"class,omitempty"`
	Missing  []string `json:"missing,omitempty" yaml:"missing,omitempty"`
	Extra    []string `json:"extra,omitempty" yaml:"extra,omitempty"`
}

DNSDifference is one normalized disagreement between resolvers.

type DNSFlags

type DNSFlags struct {
	Response           bool `json:"response" yaml:"response"`
	Authoritative      bool `json:"authoritative" yaml:"authoritative"`
	Truncated          bool `json:"truncated" yaml:"truncated"`
	RecursionDesired   bool `json:"recursion_desired" yaml:"recursion_desired"`
	RecursionAvailable bool `json:"recursion_available" yaml:"recursion_available"`
	AuthenticatedData  bool `json:"authenticated_data" yaml:"authenticated_data"`
	CheckingDisabled   bool `json:"checking_disabled" yaml:"checking_disabled"`
}

DNSFlags is the stable subset of a DNS message header useful to callers.

type DNSMessage

type DNSMessage struct {
	Name           string        `json:"name" yaml:"name"`
	Type           string        `json:"type" yaml:"type"`
	Class          string        `json:"class" yaml:"class"`
	Resolver       string        `json:"resolver" yaml:"resolver"`
	Transport      string        `json:"transport" yaml:"transport"`
	Server         string        `json:"server" yaml:"server"`
	Duration       time.Duration `json:"duration_ns" yaml:"duration_ns"`
	ID             uint16        `json:"id" yaml:"id"`
	Opcode         string        `json:"opcode" yaml:"opcode"`
	Rcode          string        `json:"rcode" yaml:"rcode"`
	Flags          DNSFlags      `json:"flags" yaml:"flags"`
	Answer         []DNSRecord   `json:"answer,omitempty" yaml:"answer,omitempty"`
	Authority      []DNSRecord   `json:"authority,omitempty" yaml:"authority,omitempty"`
	Additional     []DNSRecord   `json:"additional,omitempty" yaml:"additional,omitempty"`
	ExtendedErrors []string      `json:"extended_errors,omitempty" yaml:"extended_errors,omitempty"`
	DNSSEC         string        `json:"dnssec" yaml:"dnssec"`
	Raw            []byte        `json:"raw,omitempty" yaml:"raw,omitempty"`
	Error          string        `json:"error,omitempty" yaml:"error,omitempty"`
}

DNSMessage captures one complete DNS exchange, including every response section and transport metadata.

type DNSMode

type DNSMode string

DNSMode controls optional DNS enrichment for a lookup. A zero-value LookupOptions leaves DNS disabled; DNSAuto remains available for callers that want domain-only discovery without special-casing non-domain targets.

const (
	DNSAuto DNSMode = "auto"
	DNSOff  DNSMode = "off"
	DNSScan DNSMode = "scan"
	DNSAXFR DNSMode = "axfr"
)

type DNSOperationResult

type DNSOperationResult struct {
	Mode        string                 `json:"mode" yaml:"mode"`
	Messages    []DNSMessage           `json:"messages,omitempty" yaml:"messages,omitempty"`
	Inventory   *DNSResult             `json:"inventory,omitempty" yaml:"inventory,omitempty"`
	Differences []DNSDifference        `json:"differences,omitempty" yaml:"differences,omitempty"`
	Trace       []DNSTraceHop          `json:"trace,omitempty" yaml:"trace,omitempty"`
	Transfer    *DNSResult             `json:"transfer,omitempty" yaml:"transfer,omitempty"`
	Warnings    []string               `json:"warnings,omitempty" yaml:"warnings,omitempty"`
	Remote      []RemoteDNSMeasurement `json:"remote,omitempty" yaml:"remote,omitempty"`
}

DNSOperationResult is the common result for every DNS engine operation.

type DNSOptions

type DNSOptions struct {
	Types                []string         `json:"types,omitempty" yaml:"types,omitempty"`
	Class                string           `json:"class,omitempty" yaml:"class,omitempty"`
	Resolvers            []string         `json:"resolvers,omitempty" yaml:"resolvers,omitempty"`
	Strategy             ResolverStrategy `json:"strategy,omitempty" yaml:"strategy,omitempty"`
	Recursive            *bool            `json:"recursive,omitempty" yaml:"recursive,omitempty"`
	CheckingDisabled     bool             `json:"checking_disabled,omitempty" yaml:"checking_disabled,omitempty"`
	AuthoritativeOnly    bool             `json:"authoritative_only,omitempty" yaml:"authoritative_only,omitempty"`
	EDNS                 EDNSOptions      `json:"edns,omitempty" yaml:"edns,omitempty"`
	Transfer             TransferOptions  `json:"transfer,omitempty" yaml:"transfer,omitempty"`
	Globalping           bool             `json:"globalping,omitempty" yaml:"globalping,omitempty"`
	GlobalpingLocations  []string         `json:"globalping_locations,omitempty" yaml:"globalping_locations,omitempty"`
	GlobalpingLimit      int              `json:"globalping_limit,omitempty" yaml:"globalping_limit,omitempty"`
	GlobalpingToken      string           `json:"-" yaml:"-"`
	GlobalpingEndpoint   string           `json:"-" yaml:"-"`
	GlobalpingHTTPClient *http.Client     `json:"-" yaml:"-"`
}

DNSOptions controls query, inventory, comparison, trace, and transfer.

type DNSProvider

DNSProvider is the dependency-injection boundary for DNS operations.

type DNSRecord

type DNSRecord struct {
	Name  string `json:"name" yaml:"name"`
	Type  string `json:"type" yaml:"type"`
	TTL   uint32 `json:"ttl" yaml:"ttl"`
	Value string `json:"value" yaml:"value"`
}

DNSRecord is one public DNS resource record. Value is canonical DNS RDATA text, suitable for display and zone-file-oriented export.

type DNSResult

type DNSResult struct {
	Method      string      `json:"method" yaml:"method"`
	Complete    bool        `json:"complete" yaml:"complete"`
	Nameservers []string    `json:"nameservers,omitempty" yaml:"nameservers,omitempty"`
	Records     []DNSRecord `json:"records,omitempty" yaml:"records,omitempty"`
	Warnings    []string    `json:"warnings,omitempty" yaml:"warnings,omitempty"`
}

DNSResult records records discovered alongside registration data. Complete is true only when an untruncated authoritative AXFR completed successfully. Pattern scans intentionally remain incomplete: DNS has no reliable general mechanism to enumerate arbitrary owner names in a zone.

type DNSTraceHop

type DNSTraceHop struct {
	Zone        string        `json:"zone" yaml:"zone"`
	Server      string        `json:"server" yaml:"server"`
	Duration    time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Rcode       string        `json:"rcode" yaml:"rcode"`
	Nameservers []string      `json:"nameservers,omitempty" yaml:"nameservers,omitempty"`
	Addresses   []string      `json:"addresses,omitempty" yaml:"addresses,omitempty"`
	DNSSEC      string        `json:"dnssec" yaml:"dnssec"`
	Glue        string        `json:"glue,omitempty" yaml:"glue,omitempty"`
	Lame        bool          `json:"lame,omitempty" yaml:"lame,omitempty"`
	Error       string        `json:"error,omitempty" yaml:"error,omitempty"`
}

DNSTraceHop is one iterative delegation step.

type DiagnoseOptions

type DiagnoseOptions struct {
	DNS          DNSOptions    `json:"dns,omitempty" yaml:"dns,omitempty"`
	Timeout      time.Duration `json:"-" yaml:"-"`
	Trace        bool          `json:"trace,omitempty" yaml:"trace,omitempty"`
	Remote       bool          `json:"remote,omitempty" yaml:"remote,omitempty"`
	MaxAddresses int           `json:"max_addresses,omitempty" yaml:"max_addresses,omitempty"`
}

DiagnoseOptions controls bounded, domain-derived connectivity checks. Ports are obtained from established protocols and advertised DNS service records; this API is intentionally not a general-purpose port scanner.

type DiagnoseProvider

type DiagnoseProvider interface {
	Diagnose(context.Context, string, DiagnoseOptions) (*DiagnosisReport, error)
}

DiagnoseProvider is the dependency-injection boundary for domain checks.

type DiagnosisReport

type DiagnosisReport struct {
	Domain       string              `json:"domain" yaml:"domain"`
	DNS          *DNSOperationResult `json:"dns,omitempty" yaml:"dns,omitempty"`
	Delegation   *DNSOperationResult `json:"delegation,omitempty" yaml:"delegation,omitempty"`
	Reachability []AddressProbe      `json:"reachability,omitempty" yaml:"reachability,omitempty"`
	HTTP         []HTTPProbe         `json:"http,omitempty" yaml:"http,omitempty"`
	TLS          []TLSProbe          `json:"tls,omitempty" yaml:"tls,omitempty"`
	Mail         []MailProbe         `json:"mail,omitempty" yaml:"mail,omitempty"`
	Services     []ServiceProbe      `json:"services,omitempty" yaml:"services,omitempty"`
	Path         []PathHop           `json:"path,omitempty" yaml:"path,omitempty"`
	Policies     map[string][]string `json:"policies,omitempty" yaml:"policies,omitempty"`
	Findings     []Finding           `json:"findings,omitempty" yaml:"findings,omitempty"`
	Warnings     []string            `json:"warnings,omitempty" yaml:"warnings,omitempty"`
}

DiagnosisReport is the structured output of the bounded diagnosis engine.

type EDNSOptions

type EDNSOptions struct {
	BufferSize uint16 `json:"buffer_size,omitempty" yaml:"buffer_size,omitempty"`
	DNSSEC     bool   `json:"dnssec,omitempty" yaml:"dnssec,omitempty"`
	NSID       bool   `json:"nsid,omitempty" yaml:"nsid,omitempty"`
	ECS        string `json:"ecs,omitempty" yaml:"ecs,omitempty"`
	Cookie     string `json:"cookie,omitempty" yaml:"cookie,omitempty"`
	Padding    uint16 `json:"padding,omitempty" yaml:"padding,omitempty"`
}

EDNSOptions configures the OPT pseudo-record used for DNS queries.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine coordinates independent providers behind one public API.

func NewEngine

func NewEngine(options EngineOptions) *Engine

NewEngine creates a domain-workstation engine without performing network activity. Nil providers are replaced by Whodis's built-in implementations.

func (*Engine) Close

func (engine *Engine) Close() error

Close releases reusable transports owned by the engine.

func (*Engine) Run

func (engine *Engine) Run(ctx context.Context, request Request) (Report, error)

Run performs exactly one requested operation. A successfully returned report may contain scoped errors alongside partial results; an error is reserved for invalid requests or a canceled/deadline-exceeded operation with no result.

func (*Engine) RunBatch

func (engine *Engine) RunBatch(ctx context.Context, batch BatchRequest) (BatchReport, error)

RunBatch performs independent requests with bounded concurrency while preserving input order.

func (*Engine) RunStream

func (engine *Engine) RunStream(ctx context.Context, requests <-chan Request, options StreamOptions, emit func(StreamItem) error) error

RunStream consumes requests incrementally and emits completed reports in completion order. Index preserves input attribution without materializing a complete BatchReport.

type EngineLimits

type EngineLimits struct {
	RegistrationConcurrency int
	ProbeConcurrency        int
	MaximumBatchItems       int
}

EngineLimits bounds nested fan-out for reusable engines and embedded use.

type EngineOptions

type EngineOptions struct {
	Client        *Client
	Registration  RegistrationProvider
	DNS           DNSProvider
	Diagnose      DiagnoseProvider
	Investigation InvestigationProvider
	Enrichments   map[string]EnrichmentProvider
	Timeout       time.Duration
	NetworkPolicy NetworkPolicy
	Limits        EngineLimits
}

EngineOptions configures a reusable, concurrency-safe engine.

type EnrichmentOptions added in v2.1.0

type EnrichmentOptions struct {
	Limit      int
	Endpoint   string
	Token      string
	HTTPClient *http.Client
}

EnrichmentOptions are shared controls passed to a named provider.

type EnrichmentProvider added in v2.1.0

type EnrichmentProvider interface {
	Name() string
	Enrich(context.Context, InvestigationSeed, EnrichmentOptions) (EnrichmentResult, error)
}

EnrichmentProvider is the library extension point for passive intelligence sources. Providers are registered by Name through EngineOptions.

type EnrichmentResult added in v2.1.0

type EnrichmentResult struct {
	Related  []RelatedObservation
	Total    int
	Warnings []string
}

EnrichmentResult is a provider's bounded set of historical observations.

type Entity

type Entity struct {
	Roles        []string `json:"roles,omitempty" yaml:"roles,omitempty"`
	Handle       string   `json:"handle,omitempty" yaml:"handle,omitempty"`
	Name         string   `json:"name,omitempty" yaml:"name,omitempty"`
	Organization string   `json:"organization,omitempty" yaml:"organization,omitempty"`
	Email        string   `json:"email,omitempty" yaml:"email,omitempty"`
	Phone        string   `json:"phone,omitempty" yaml:"phone,omitempty"`
}

Entity contains public contact or organization information. Fields that are redacted by a registry remain absent rather than being invented.

type ErrorKind

type ErrorKind string

ErrorKind allows command-line callers and future UIs to handle lookup failures without string matching.

const (
	ErrorInvalidInput ErrorKind = "invalid_input"
	ErrorNotFound     ErrorKind = "not_found"
	ErrorRateLimited  ErrorKind = "rate_limited"
	ErrorDiscovery    ErrorKind = "discovery"
	ErrorUnavailable  ErrorKind = "unavailable"
	ErrorProtocol     ErrorKind = "protocol"
	ErrorCanceled     ErrorKind = "canceled"
	ErrorTimeout      ErrorKind = "timeout"
)

type Event

type Event struct {
	Action string `json:"action" yaml:"action"`
	Date   string `json:"date" yaml:"date"`
}

Event is a dated registration event such as registration or expiration.

type FallbackMode

type FallbackMode string

FallbackMode controls whether Whodis tries the other protocol after its knowledge-based primary route fails.

const (
	FallbackUnavailable FallbackMode = "unavailable"
	FallbackNone        FallbackMode = "none"
	FallbackAnyError    FallbackMode = "any-error"
)

type Finding

type Finding struct {
	ID       string            `json:"id" yaml:"id"`
	Severity Severity          `json:"severity" yaml:"severity"`
	Title    string            `json:"title" yaml:"title"`
	Summary  string            `json:"summary" yaml:"summary"`
	Evidence map[string]string `json:"evidence,omitempty" yaml:"evidence,omitempty"`
}

Finding is one deterministic diagnostic observation. Whodis intentionally does not collapse findings into an opaque overall score.

type Format

type Format string

Format is an output representation for a LookupResult.

const (
	FormatPretty   Format = "pretty"
	FormatTree     Format = "tree"
	FormatGeekBoys Format = "geekboys"
	FormatPlain    Format = "plain"
	FormatJSON     Format = "json"
	FormatYAML     Format = "yaml"
	FormatCSV      Format = "csv"
	FormatNDJSON   Format = "ndjson"
	FormatMarkdown Format = "markdown"
	FormatRaw      Format = "raw"
)

func ParseFormat

func ParseFormat(value string) (Format, error)

ParseFormat validates a CLI-facing output format. Common descriptions of the human-facing renderers are accepted as friendly aliases.

type HTTPProbe

type HTTPProbe struct {
	URL       string        `json:"url" yaml:"url"`
	Status    int           `json:"status,omitempty" yaml:"status,omitempty"`
	FinalURL  string        `json:"final_url,omitempty" yaml:"final_url,omitempty"`
	Redirects []string      `json:"redirects,omitempty" yaml:"redirects,omitempty"`
	Duration  time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Server    string        `json:"server,omitempty" yaml:"server,omitempty"`
	Healthy   bool          `json:"healthy" yaml:"healthy"`
	Error     string        `json:"error,omitempty" yaml:"error,omitempty"`
	// contains filtered or unexported fields
}

HTTPProbe captures one HTTP endpoint and its final response.

type HomepageAccessibilityProfile added in v2.4.0

type HomepageAccessibilityProfile struct {
	Language                 bool `json:"language" yaml:"language"`
	ImagesMissingAlt         int  `json:"images_missing_alt" yaml:"images_missing_alt"`
	FormControls             int  `json:"form_controls" yaml:"form_controls"`
	FormControlsMissingLabel int  `json:"form_controls_missing_label" yaml:"form_controls_missing_label"`
}

type HomepageAssetProfile added in v2.4.0

type HomepageAssetProfile struct {
	Scripts                    int      `json:"scripts" yaml:"scripts"`
	InlineScripts              int      `json:"inline_scripts" yaml:"inline_scripts"`
	AsyncScripts               int      `json:"async_scripts" yaml:"async_scripts"`
	DeferredScripts            int      `json:"deferred_scripts" yaml:"deferred_scripts"`
	ModuleScripts              int      `json:"module_scripts" yaml:"module_scripts"`
	PotentiallyBlockingScripts int      `json:"potentially_blocking_scripts" yaml:"potentially_blocking_scripts"`
	ScriptsWithMinifiedName    int      `json:"scripts_with_minified_name" yaml:"scripts_with_minified_name"`
	Stylesheets                int      `json:"stylesheets" yaml:"stylesheets"`
	StylesWithMinifiedName     int      `json:"styles_with_minified_name" yaml:"styles_with_minified_name"`
	Images                     int      `json:"images" yaml:"images"`
	LazyImages                 int      `json:"lazy_images" yaml:"lazy_images"`
	ImagesWithDimensions       int      `json:"images_with_dimensions" yaml:"images_with_dimensions"`
	Preloads                   int      `json:"preloads" yaml:"preloads"`
	Preconnects                int      `json:"preconnects" yaml:"preconnects"`
	ThirdPartyOriginTotal      int      `json:"third_party_origin_total" yaml:"third_party_origin_total"`
	ThirdPartyOrigins          []string `json:"third_party_origins,omitempty" yaml:"third_party_origins,omitempty"`
}

type HomepageMetadataProfile added in v2.4.0

type HomepageMetadataProfile struct {
	Title           bool     `json:"title" yaml:"title"`
	MetaDescription bool     `json:"meta_description" yaml:"meta_description"`
	CanonicalURL    string   `json:"canonical_url,omitempty" yaml:"canonical_url,omitempty"`
	Viewport        bool     `json:"viewport" yaml:"viewport"`
	Robots          []string `json:"robots,omitempty" yaml:"robots,omitempty"`
	H1Count         int      `json:"h1_count" yaml:"h1_count"`
	StructuredData  int      `json:"structured_data" yaml:"structured_data"`
	OpenGraph       bool     `json:"open_graph" yaml:"open_graph"`
	TwitterCards    bool     `json:"twitter_cards" yaml:"twitter_cards"`
}

type HomepageMinification added in v2.4.0

type HomepageMinification string

HomepageMinification is a conservative source-formatting observation. It is not a browser performance score and says nothing about fetched assets.

const (
	HomepageMinificationLikely      HomepageMinification = "likely"
	HomepageMinificationNotObserved HomepageMinification = "not_observed"
	HomepageMinificationUnknown     HomepageMinification = "unknown"
)

type HomepageProfile added in v2.4.0

type HomepageProfile struct {
	URL              string                       `json:"url" yaml:"url"`
	Status           int                          `json:"status,omitempty" yaml:"status,omitempty"`
	HTTPVersion      string                       `json:"http_version,omitempty" yaml:"http_version,omitempty"`
	ContentType      string                       `json:"content_type,omitempty" yaml:"content_type,omitempty"`
	ContentEncoding  string                       `json:"content_encoding,omitempty" yaml:"content_encoding,omitempty"`
	ContentLength    int64                        `json:"content_length,omitempty" yaml:"content_length,omitempty"`
	DecodedBytes     int                          `json:"decoded_bytes,omitempty" yaml:"decoded_bytes,omitempty"`
	Truncated        bool                         `json:"truncated,omitempty" yaml:"truncated,omitempty"`
	CacheControl     string                       `json:"cache_control,omitempty" yaml:"cache_control,omitempty"`
	ETag             bool                         `json:"etag,omitempty" yaml:"etag,omitempty"`
	LastModified     bool                         `json:"last_modified,omitempty" yaml:"last_modified,omitempty"`
	MarkupAnalyzed   bool                         `json:"markup_analyzed" yaml:"markup_analyzed"`
	HTMLMinification HomepageMinification         `json:"html_minification" yaml:"html_minification"`
	FormattingBytes  int                          `json:"formatting_bytes,omitempty" yaml:"formatting_bytes,omitempty"`
	Assets           HomepageAssetProfile         `json:"assets" yaml:"assets"`
	Metadata         HomepageMetadataProfile      `json:"metadata" yaml:"metadata"`
	Security         HomepageSecurityProfile      `json:"security" yaml:"security"`
	Accessibility    HomepageAccessibilityProfile `json:"accessibility" yaml:"accessibility"`
}

HomepageProfile contains bounded facts extracted from the one homepage response already fetched by Investigate. It never contains the response body.

type HomepageSecurityProfile added in v2.4.0

type HomepageSecurityProfile struct {
	HTTPS                  bool `json:"https" yaml:"https"`
	HSTS                   bool `json:"hsts" yaml:"hsts"`
	CSP                    bool `json:"csp" yaml:"csp"`
	FrameProtection        bool `json:"frame_protection" yaml:"frame_protection"`
	NoSniff                bool `json:"no_sniff" yaml:"no_sniff"`
	ReferrerPolicy         bool `json:"referrer_policy" yaml:"referrer_policy"`
	PermissionsPolicy      bool `json:"permissions_policy" yaml:"permissions_policy"`
	MixedContentReferences int  `json:"mixed_content_references" yaml:"mixed_content_references"`
}

type InvestigationEvidence added in v2.1.0

type InvestigationEvidence struct {
	Source  string `json:"source" yaml:"source"`
	Subject string `json:"subject,omitempty" yaml:"subject,omitempty"`
	Field   string `json:"field" yaml:"field"`
	Value   string `json:"value" yaml:"value"`
}

InvestigationEvidence is one bounded public observation supporting a stack component. Values are short display-safe excerpts, never response bodies.

type InvestigationLink struct {
	Label string `json:"label" yaml:"label"`
	Type  string `json:"type" yaml:"type"`
	Value string `json:"value" yaml:"value"`
	URL   string `json:"url" yaml:"url"`
}

InvestigationLink is a resolved, user-opened pivot. Whodis never opens a link or contacts its destination without an explicit user action.

type InvestigationLinkProvider added in v2.3.0

type InvestigationLinkProvider struct {
	ID      string   `json:"id" yaml:"id"`
	Label   string   `json:"label" yaml:"label"`
	Purpose string   `json:"purpose" yaml:"purpose"`
	Tier    string   `json:"tier" yaml:"tier"`
	Targets []string `json:"targets" yaml:"targets"`
}

InvestigationLinkProvider describes one locally generated manual research pivot. Targets are domain, ipv4, and/or ipv6. Building a link never contacts the provider.

func AvailableInvestigationLinkProviders added in v2.3.0

func AvailableInvestigationLinkProviders() []InvestigationLinkProvider

AvailableInvestigationLinkProviders returns the manual-link catalog in its stable display order. The returned values do not expose executable builders.

type InvestigationOptions added in v2.1.0

type InvestigationOptions struct {
	DNS                  DNSOptions   `json:"dns,omitempty" yaml:"dns,omitempty"`
	Enrichments          []string     `json:"enrichments,omitempty" yaml:"enrichments,omitempty"`
	RelatedLimit         int          `json:"related_limit,omitempty" yaml:"related_limit,omitempty"`
	LinkProviders        []string     `json:"link_providers,omitempty" yaml:"link_providers,omitempty"`
	ExternalLinkTemplate string       `json:"external_link_template,omitempty" yaml:"external_link_template,omitempty"`
	OTXEndpoint          string       `json:"otx_endpoint,omitempty" yaml:"otx_endpoint,omitempty"`
	OTXToken             string       `json:"-" yaml:"-"`
	HTTPClient           *http.Client `json:"-" yaml:"-"`
}

InvestigationOptions controls bounded local profiling and explicitly named third-party enrichments. Tokens and clients are never serialized.

type InvestigationProvider added in v2.1.0

type InvestigationProvider interface {
	Investigate(context.Context, Subject, *DiagnosisReport, InvestigationOptions) (*InvestigationReport, error)
}

InvestigationProvider turns live diagnostic evidence into an explainable technology and infrastructure profile. Implementations may return partial reports together with an error when optional enrichment is unavailable.

type InvestigationReport added in v2.1.0

type InvestigationReport struct {
	Domain         string               `json:"domain" yaml:"domain"`
	Summary        string               `json:"summary" yaml:"summary"`
	Components     []StackComponent     `json:"components,omitempty" yaml:"components,omitempty"`
	Homepage       *HomepageProfile     `json:"homepage,omitempty" yaml:"homepage,omitempty"`
	Networks       []NetworkObservation `json:"networks,omitempty" yaml:"networks,omitempty"`
	Related        []RelatedObservation `json:"related,omitempty" yaml:"related,omitempty"`
	RelatedTotal   int                  `json:"related_total,omitempty" yaml:"related_total,omitempty"`
	Links          []InvestigationLink  `json:"links,omitempty" yaml:"links,omitempty"`
	Warnings       []string             `json:"warnings,omitempty" yaml:"warnings,omitempty"`
	Findings       []Finding            `json:"findings,omitempty" yaml:"findings,omitempty"`
	ProviderErrors []OperationError     `json:"-" yaml:"-"`
}

InvestigationReport is the renderer-independent technology and infrastructure profile attached to an investigate report.

type InvestigationSeed added in v2.1.0

type InvestigationSeed struct {
	Subject   Subject  `json:"subject" yaml:"subject"`
	Addresses []string `json:"addresses" yaml:"addresses"`
}

InvestigationSeed is the public, bounded input given to enrichment providers. Addresses are public representative A/AAAA results only.

type Kind

type Kind string

Kind is the kind of registration object represented by a Target.

const (
	KindDomain Kind = "domain"
	KindIP     Kind = "ip"
	KindASN    Kind = "asn"
)

type LookupError

type LookupError struct {
	Kind    ErrorKind
	Message string
	Cause   error
}

LookupError wraps a failure with an actionable classification.

func (*LookupError) Error

func (e *LookupError) Error() string

func (*LookupError) Unwrap

func (e *LookupError) Unwrap() error

type LookupOptions

type LookupOptions struct {
	Protocol         Protocol
	Fallback         FallbackMode
	Server           string
	Timeout          time.Duration
	RefreshBootstrap bool
	DNSMode          DNSMode
	DNSResolver      string
}

LookupOptions controls one lookup. A zero-value options struct uses the knowledge-based automatic protocol router, unavailable-only fallback, and no live DNS enrichment.

type LookupResult

type LookupResult struct {
	SchemaVersion int            `json:"schema_version" yaml:"schema_version"`
	Query         Target         `json:"query" yaml:"query"`
	Route         RouteDecision  `json:"route" yaml:"route"`
	FallbackFrom  *RouteDecision `json:"fallback_from,omitempty" yaml:"fallback_from,omitempty"`
	RetrievedAt   time.Time      `json:"retrieved_at" yaml:"retrieved_at"`
	Object        Object         `json:"object" yaml:"object"`
	Sources       []Source       `json:"sources" yaml:"sources"`
	DNS           *DNSResult     `json:"dns,omitempty" yaml:"dns,omitempty"`
}

LookupResult is the serializable response returned by Client.Lookup.

type MailProbe

type MailProbe struct {
	Host         string        `json:"host" yaml:"host"`
	Preference   uint16        `json:"preference" yaml:"preference"`
	Address      string        `json:"address,omitempty" yaml:"address,omitempty"`
	Reachable    bool          `json:"reachable" yaml:"reachable"`
	Greeting     string        `json:"greeting,omitempty" yaml:"greeting,omitempty"`
	Capabilities []string      `json:"capabilities,omitempty" yaml:"capabilities,omitempty"`
	STARTTLS     bool          `json:"starttls" yaml:"starttls"`
	TLSVerified  bool          `json:"tls_verified,omitempty" yaml:"tls_verified,omitempty"`
	TLSVersion   string        `json:"tls_version,omitempty" yaml:"tls_version,omitempty"`
	Duration     time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Error        string        `json:"error,omitempty" yaml:"error,omitempty"`
	// contains filtered or unexported fields
}

MailProbe captures one MX SMTP greeting and advertised capabilities.

type NetworkObservation added in v2.1.0

type NetworkObservation struct {
	Address     string              `json:"address" yaml:"address"`
	PTR         []string            `json:"ptr,omitempty" yaml:"ptr,omitempty"`
	NetworkName string              `json:"network_name,omitempty" yaml:"network_name,omitempty"`
	Operator    string              `json:"operator,omitempty" yaml:"operator,omitempty"`
	Provider    string              `json:"provider,omitempty" yaml:"provider,omitempty"`
	CIDR        []string            `json:"cidr,omitempty" yaml:"cidr,omitempty"`
	Country     string              `json:"country,omitempty" yaml:"country,omitempty"`
	Source      string              `json:"source,omitempty" yaml:"source,omitempty"`
	Links       []InvestigationLink `json:"links,omitempty" yaml:"links,omitempty"`
}

NetworkObservation attributes one public web address without conflating the network operator with the site's customer-facing hosting provider.

type NetworkPolicy

type NetworkPolicy struct {
	AllowPrivate      bool `json:"allow_private,omitempty" yaml:"allow_private,omitempty"`
	AllowInsecureHTTP bool `json:"allow_insecure_http,omitempty" yaml:"allow_insecure_http,omitempty"`
}

NetworkPolicy controls exceptional access to private network destinations. Automatically discovered referrals and diagnostic targets remain restricted to public addresses by default.

type Notice

type Notice struct {
	Title       string   `json:"title,omitempty" yaml:"title,omitempty"`
	Description []string `json:"description,omitempty" yaml:"description,omitempty"`
	Links       []string `json:"links,omitempty" yaml:"links,omitempty"`
}

Notice is a registry-supplied legal or service notice.

type Object

type Object struct {
	Kind         Kind                `json:"kind" yaml:"kind"`
	Handle       string              `json:"handle,omitempty" yaml:"handle,omitempty"`
	Name         string              `json:"name,omitempty" yaml:"name,omitempty"`
	UnicodeName  string              `json:"unicode_name,omitempty" yaml:"unicode_name,omitempty"`
	Status       []string            `json:"status,omitempty" yaml:"status,omitempty"`
	Events       []Event             `json:"events,omitempty" yaml:"events,omitempty"`
	Nameservers  []string            `json:"nameservers,omitempty" yaml:"nameservers,omitempty"`
	Entities     []Entity            `json:"entities,omitempty" yaml:"entities,omitempty"`
	Registrar    string              `json:"registrar,omitempty" yaml:"registrar,omitempty"`
	Registry     string              `json:"registry,omitempty" yaml:"registry,omitempty"`
	DNSSEC       string              `json:"dnssec,omitempty" yaml:"dnssec,omitempty"`
	StartAddress string              `json:"start_address,omitempty" yaml:"start_address,omitempty"`
	EndAddress   string              `json:"end_address,omitempty" yaml:"end_address,omitempty"`
	CIDR         []string            `json:"cidr,omitempty" yaml:"cidr,omitempty"`
	Country      string              `json:"country,omitempty" yaml:"country,omitempty"`
	NetworkType  string              `json:"network_type,omitempty" yaml:"network_type,omitempty"`
	ASN          string              `json:"asn,omitempty" yaml:"asn,omitempty"`
	ASNName      string              `json:"asn_name,omitempty" yaml:"asn_name,omitempty"`
	ASNType      string              `json:"asn_type,omitempty" yaml:"asn_type,omitempty"`
	Notices      []Notice            `json:"notices,omitempty" yaml:"notices,omitempty"`
	Extras       map[string][]string `json:"extras,omitempty" yaml:"extras,omitempty"`
}

Object is Whodis's stable normalized registration-data model. Extras keeps protocol or registry-specific values that do not fit the common fields.

type Operation

type Operation string

Operation identifies one engine operation.

const (
	OperationRegistration Operation = "registration"
	OperationInspect      Operation = "inspect"
	OperationDNSQuery     Operation = "dns.query"
	OperationDNSInventory Operation = "dns.inventory"
	OperationDNSCompare   Operation = "dns.compare"
	OperationDNSTrace     Operation = "dns.trace"
	OperationDNSTransfer  Operation = "dns.transfer"
	OperationDiagnose     Operation = "diagnose"
	OperationInvestigate  Operation = "investigate"
)

type OperationError

type OperationError struct {
	Operation Operation `json:"operation" yaml:"operation"`
	Provider  string    `json:"provider,omitempty" yaml:"provider,omitempty"`
	Kind      ErrorKind `json:"kind" yaml:"kind"`
	Message   string    `json:"message" yaml:"message"`
}

OperationError is a serializable, provider-scoped failure. Reports may contain errors and useful results at the same time.

type PathHop

type PathHop struct {
	Hop      int           `json:"hop" yaml:"hop"`
	Address  string        `json:"address,omitempty" yaml:"address,omitempty"`
	Duration time.Duration `json:"duration_ns,omitempty" yaml:"duration_ns,omitempty"`
	Reached  bool          `json:"reached" yaml:"reached"`
	Error    string        `json:"error,omitempty" yaml:"error,omitempty"`
}

PathHop is one hop from an explicitly requested local network path trace.

type ProgressEvent

type ProgressEvent struct {
	RequestID string    `json:"request_id,omitempty" yaml:"request_id,omitempty"`
	Operation Operation `json:"operation" yaml:"operation"`
	Target    string    `json:"target" yaml:"target"`
	Stage     string    `json:"stage" yaml:"stage"`
	Completed int       `json:"completed,omitempty" yaml:"completed,omitempty"`
	Total     int       `json:"total,omitempty" yaml:"total,omitempty"`
}

ProgressEvent is emitted at stable operation boundaries. Callbacks are serialized by Engine.RunBatch and should return quickly.

type ProjectionField

type ProjectionField string

ProjectionField is a stable, script-friendly view of a normalized result.

const (
	FieldExpiration   ProjectionField = "expiration"
	FieldRegistration ProjectionField = "registration"
	FieldUpdated      ProjectionField = "updated"
	FieldRegistrar    ProjectionField = "registrar"
	FieldRegistry     ProjectionField = "registry"
	FieldStatus       ProjectionField = "status"
	FieldNameservers  ProjectionField = "nameservers"
	FieldDNSSEC       ProjectionField = "dnssec"
	FieldProtocol     ProjectionField = "protocol"
)

func ParseProjectionField

func ParseProjectionField(value string) (ProjectionField, error)

ParseProjectionField validates a CLI- or UI-facing field name.

type Protocol

type Protocol string

Protocol is a registration-data transport.

const (
	ProtocolAuto   Protocol = "auto"
	ProtocolRDAP   Protocol = "rdap"
	ProtocolWHOIS  Protocol = "whois"
	ProtocolRWHOIS Protocol = "rwhois"
)

type ProtocolAdapter

type ProtocolAdapter interface {
	Protocol() Protocol
	Lookup(ctx context.Context, target Target, route RouteDecision) (Object, []Source, error)
}

ProtocolAdapter is the extension point for registration-data protocols. Implementations are supplied to NewClient rather than loaded through Go's platform-limited plugin mechanism.

type RegistrationProvider

type RegistrationProvider interface {
	Lookup(context.Context, Subject, LookupOptions) (RegistrationResult, error)
}

RegistrationProvider is the dependency-injection boundary for normalized registration lookup implementations.

type RegistrationResult

type RegistrationResult struct {
	Route        RouteDecision  `json:"route" yaml:"route"`
	FallbackFrom *RouteDecision `json:"fallback_from,omitempty" yaml:"fallback_from,omitempty"`
	Object       Object         `json:"object" yaml:"object"`
	Sources      []Source       `json:"sources" yaml:"sources"`
}

RegistrationResult is the normalized registration portion of a v5 report. Query identity and observation time live once on the enclosing Report.

func (RegistrationResult) AsLookupResult

func (result RegistrationResult) AsLookupResult(subject Subject, observedAt time.Time) LookupResult

AsLookupResult converts a v5 registration section for consumers migrating from Whodis v1's standalone lookup model.

type RelatedObservation added in v2.1.0

type RelatedObservation struct {
	Provider      string       `json:"provider" yaml:"provider"`
	Hostname      string       `json:"hostname" yaml:"hostname"`
	Address       string       `json:"address" yaml:"address"`
	RecordType    string       `json:"record_type,omitempty" yaml:"record_type,omitempty"`
	ASN           string       `json:"asn,omitempty" yaml:"asn,omitempty"`
	FirstSeen     time.Time    `json:"first_seen,omitempty" yaml:"first_seen,omitempty"`
	LastSeen      time.Time    `json:"last_seen,omitempty" yaml:"last_seen,omitempty"`
	Current       RelatedState `json:"current" yaml:"current"`
	CurrentValues []string     `json:"current_values,omitempty" yaml:"current_values,omitempty"`
}

RelatedObservation is one historical provider observation, optionally checked against current DNS. It is not an ownership assertion.

type RelatedState added in v2.1.0

type RelatedState string

RelatedState says whether a passive observation still resolves to the address on which it was observed.

const (
	RelatedCurrent RelatedState = "current"
	RelatedStale   RelatedState = "stale"
	RelatedUnknown RelatedState = "unknown"
)

type RemoteDNSMeasurement

type RemoteDNSMeasurement struct {
	MeasurementID string        `json:"measurement_id" yaml:"measurement_id"`
	Status        string        `json:"status" yaml:"status"`
	Probe         string        `json:"probe,omitempty" yaml:"probe,omitempty"`
	Location      string        `json:"location,omitempty" yaml:"location,omitempty"`
	Resolver      string        `json:"resolver,omitempty" yaml:"resolver,omitempty"`
	Rcode         string        `json:"rcode,omitempty" yaml:"rcode,omitempty"`
	Duration      time.Duration `json:"duration_ns,omitempty" yaml:"duration_ns,omitempty"`
	Answers       []DNSRecord   `json:"answers,omitempty" yaml:"answers,omitempty"`
	Raw           string        `json:"raw,omitempty" yaml:"raw,omitempty"`
	Error         string        `json:"error,omitempty" yaml:"error,omitempty"`
}

RemoteDNSMeasurement is one explicitly requested Globalping probe result.

type RenderOptions

type RenderOptions struct {
	Color   string
	Width   int
	Details bool
}

RenderOptions changes presentation only; it never changes lookup behavior.

type Report

type Report struct {
	SchemaVersion int                  `json:"schema_version" yaml:"schema_version"`
	RequestID     string               `json:"request_id,omitempty" yaml:"request_id,omitempty"`
	Operation     Operation            `json:"operation" yaml:"operation"`
	Subject       Subject              `json:"subject" yaml:"subject"`
	ObservedAt    time.Time            `json:"observed_at" yaml:"observed_at"`
	Registration  *RegistrationResult  `json:"registration,omitempty" yaml:"registration,omitempty"`
	DNS           *DNSOperationResult  `json:"dns,omitempty" yaml:"dns,omitempty"`
	Diagnosis     *DiagnosisReport     `json:"diagnosis,omitempty" yaml:"diagnosis,omitempty"`
	Investigation *InvestigationReport `json:"investigation,omitempty" yaml:"investigation,omitempty"`
	Findings      []Finding            `json:"findings,omitempty" yaml:"findings,omitempty"`
	Errors        []OperationError     `json:"errors,omitempty" yaml:"errors,omitempty"`
}

Report is the renderer-independent v5 result returned by Engine.Run.

type Request

type Request struct {
	ID            string               `json:"id,omitempty" yaml:"id,omitempty"`
	Operation     Operation            `json:"operation" yaml:"operation"`
	Target        string               `json:"target" yaml:"target"`
	Registration  LookupOptions        `json:"registration,omitempty" yaml:"registration,omitempty"`
	DNS           DNSOptions           `json:"dns,omitempty" yaml:"dns,omitempty"`
	Diagnose      DiagnoseOptions      `json:"diagnose,omitempty" yaml:"diagnose,omitempty"`
	Investigation InvestigationOptions `json:"investigation,omitempty" yaml:"investigation,omitempty"`
	Timeout       time.Duration        `json:"-" yaml:"-"`
	OnProgress    func(ProgressEvent)  `json:"-" yaml:"-"`
}

Request is the stable public input to Engine.Run.

type ResolverStrategy

type ResolverStrategy string

ResolverStrategy controls how multiple configured resolvers are used.

const (
	ResolverFirst     ResolverStrategy = "first"
	ResolverAll       ResolverStrategy = "all"
	ResolverFastest   ResolverStrategy = "fastest"
	ResolverRandom    ResolverStrategy = "random"
	ResolverConsensus ResolverStrategy = "consensus"
)

type RouteDecision

type RouteDecision struct {
	Protocol        Protocol `json:"protocol" yaml:"protocol"`
	Endpoint        string   `json:"endpoint" yaml:"endpoint"`
	Alternates      []string `json:"alternates,omitempty" yaml:"alternates,omitempty"`
	DiscoverySource string   `json:"discovery_source" yaml:"discovery_source"`
	Reason          string   `json:"reason" yaml:"reason"`
}

RouteDecision records why an authority and protocol were selected.

type ServiceProbe

type ServiceProbe struct {
	Source    string        `json:"source" yaml:"source"`
	Name      string        `json:"name" yaml:"name"`
	Target    string        `json:"target" yaml:"target"`
	Port      uint16        `json:"port" yaml:"port"`
	Reachable bool          `json:"reachable" yaml:"reachable"`
	Duration  time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Error     string        `json:"error,omitempty" yaml:"error,omitempty"`
	// contains filtered or unexported fields
}

ServiceProbe captures a DNS-advertised SRV, SVCB, or HTTPS service.

type Severity

type Severity string

Severity is the deterministic outcome of a diagnostic finding.

const (
	SeverityPass    Severity = "pass"
	SeverityInfo    Severity = "info"
	SeverityWarning Severity = "warning"
	SeverityError   Severity = "error"
)

type Source

type Source struct {
	Protocol  Protocol `json:"protocol" yaml:"protocol"`
	Endpoint  string   `json:"endpoint" yaml:"endpoint"`
	Authority string   `json:"authority,omitempty" yaml:"authority,omitempty"`
	Raw       string   `json:"-" yaml:"-"`
}

Source is one registry response used to construct a result.

type StackCategory added in v2.1.0

type StackCategory string

StackCategory identifies the role a detected component plays.

const (
	StackWebApplication StackCategory = "web_application"
	StackFramework      StackCategory = "framework"
	StackWebServer      StackCategory = "web_server"
	StackEdge           StackCategory = "edge"
	StackHosting        StackCategory = "hosting"
	StackNetwork        StackCategory = "network"
	StackDNS            StackCategory = "dns"
	StackMail           StackCategory = "mail"
	StackAnalytics      StackCategory = "analytics"
	StackSecurity       StackCategory = "security"
	StackOther          StackCategory = "other"
)

type StackComponent added in v2.1.0

type StackComponent struct {
	Category      StackCategory           `json:"category" yaml:"category"`
	Name          string                  `json:"name" yaml:"name"`
	Role          string                  `json:"role,omitempty" yaml:"role,omitempty"`
	Version       string                  `json:"version,omitempty" yaml:"version,omitempty"`
	Parent        string                  `json:"parent,omitempty" yaml:"parent,omitempty"`
	Traits        []string                `json:"traits,omitempty" yaml:"traits,omitempty"`
	Basis         []string                `json:"basis,omitempty" yaml:"basis,omitempty"`
	Confidence    Confidence              `json:"confidence" yaml:"confidence"`
	Summary       string                  `json:"summary,omitempty" yaml:"summary,omitempty"`
	Evidence      []InvestigationEvidence `json:"evidence,omitempty" yaml:"evidence,omitempty"`
	EvidenceTotal int                     `json:"evidence_total,omitempty" yaml:"evidence_total,omitempty"`
}

StackComponent is one technology or provider and the evidence for its role.

type StreamItem

type StreamItem struct {
	Index  int    `json:"index" yaml:"index"`
	Report Report `json:"report" yaml:"report"`
}

StreamItem identifies a completed report by its zero-based input position.

type StreamOptions

type StreamOptions struct {
	Workers int
}

StreamOptions controls incremental batch execution without retaining every report in memory.

type Subject

type Subject struct {
	Original           string      `json:"original" yaml:"original"`
	Canonical          string      `json:"canonical" yaml:"canonical"`
	Kind               SubjectKind `json:"kind" yaml:"kind"`
	RegistrationDomain string      `json:"registration_domain,omitempty" yaml:"registration_domain,omitempty"`
}

Subject preserves the user's input while exposing the exact canonical name and, when available, the registrable domain used for registration routing.

func ParseSubject

func ParseSubject(input string, operation Operation) (Subject, error)

ParseSubject applies operation-specific target rules. Registration and composite operations accept URLs and derive the registrable domain; DNS operations accept general owner names such as _dmarc, SRV labels, wildcards, and the root zone.

type SubjectKind

type SubjectKind string

SubjectKind identifies the grammar and routing rules that apply to a request target. It deliberately distinguishes DNS owner names from registrable domains.

const (
	SubjectRegistrableDomain SubjectKind = "registrable_domain"
	SubjectDNSName           SubjectKind = "dns_name"
	SubjectIP                SubjectKind = "ip"
	SubjectPrefix            SubjectKind = "prefix"
	SubjectASN               SubjectKind = "asn"
)

type TLSProbe

type TLSProbe struct {
	Address     string        `json:"address" yaml:"address"`
	ServerName  string        `json:"server_name" yaml:"server_name"`
	Version     string        `json:"version,omitempty" yaml:"version,omitempty"`
	CipherSuite string        `json:"cipher_suite,omitempty" yaml:"cipher_suite,omitempty"`
	ALPN        string        `json:"alpn,omitempty" yaml:"alpn,omitempty"`
	Subject     string        `json:"subject,omitempty" yaml:"subject,omitempty"`
	Issuer      string        `json:"issuer,omitempty" yaml:"issuer,omitempty"`
	DNSNames    []string      `json:"dns_names,omitempty" yaml:"dns_names,omitempty"`
	NotBefore   time.Time     `json:"not_before,omitempty" yaml:"not_before,omitempty"`
	NotAfter    time.Time     `json:"not_after,omitempty" yaml:"not_after,omitempty"`
	Duration    time.Duration `json:"duration_ns" yaml:"duration_ns"`
	Verified    bool          `json:"verified" yaml:"verified"`
	Error       string        `json:"error,omitempty" yaml:"error,omitempty"`
	// contains filtered or unexported fields
}

TLSProbe captures the negotiated TLS identity and protocol.

type Target

type Target struct {
	Original  string `json:"original" yaml:"original"`
	Canonical string `json:"canonical" yaml:"canonical"`
	Kind      Kind   `json:"kind" yaml:"kind"`
}

Target is a validated, canonical lookup input.

func ParseTarget

func ParseTarget(input string) (Target, error)

ParseTarget classifies and canonicalizes one user supplied lookup target.

type TransferOptions

type TransferOptions struct {
	Type       string `json:"type,omitempty" yaml:"type,omitempty"`
	Serial     uint32 `json:"serial,omitempty" yaml:"serial,omitempty"`
	TSIGName   string `json:"tsig_name,omitempty" yaml:"tsig_name,omitempty"`
	TSIGSecret string `json:"-" yaml:"-"`
	TSIGAlgo   string `json:"tsig_algorithm,omitempty" yaml:"tsig_algorithm,omitempty"`
	TLS        bool   `json:"tls,omitempty" yaml:"tls,omitempty"`
}

TransferOptions configures an explicit AXFR or IXFR request.

Directories

Path Synopsis
Package audit provides local, deterministic snapshots, semantic diffs, and policy checks for Whodis reports.
Package audit provides local, deterministic snapshots, semantic diffs, and policy checks for Whodis reports.
cmd
whodis command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL