docs: comprehensive documentation for ExploreDNS
CI / test (pull_request) Failing after 2m13s

- Rewrite README.md with overview, features, installation (go install +
  build from source), quick start, full CLI flag reference table,
  output section descriptions, project structure, and development guide

- Add package-level doc comments to all five internal packages:
  config, dns, fingerprint, output, traverse (via doc.go or existing
  package-declaration files)

- Add GoDoc comments on every exported type, constant, function, and
  method across all packages:
  - internal/config: Config struct fields, all Parse*/Default/Validate
  - internal/dns: QueryConfig, Resolver, BasicResolver, CachingResolver,
    ExchangeFunc, RootServer, RootDiscoveryConfig, DecodedResponse,
    ResponseClassification, all exported helpers
  - internal/fingerprint: Fingerprinter, New, NewWithTimeout, Query,
    FingerprintAll
  - internal/traverse: Traverser, TraverserConfig, TraversalResult,
    Referral, ResolutionState, Response, ResponseType, InfoCache,
    Stack, TraverserHooks, EventStage, TraversalEvent, EventHandler,
    CircularReferralError, UnresolvableNameserverError
  - internal/output: Format, Config, Formatter, SummaryStats,
    NewFormatter, AttachHooks, RunTraversal, DefaultConfig,
    ComputeSummary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Gary Hansen
2026-06-08 04:01:51 +10:00
co-authored by Copilot multica-agent
parent fe1afe2a97
commit 9aa85d8e5d
21 changed files with 675 additions and 91 deletions
+21
View File
@@ -8,6 +8,13 @@ import (
miekgdns "github.com/miekg/dns"
)
// InfoCache is a two-level (parent/child) concurrent cache for NS records and
// glue addresses discovered during traversal.
//
// Lookups walk the parent chain: a child cache falls back to its parent when
// no local entry is found. Writes always go to the local cache, never to the
// parent. This makes it safe to give sibling branches separate child caches
// that share the root cache read-only in fast mode.
type InfoCache struct {
parent *InfoCache
mu sync.RWMutex
@@ -15,6 +22,8 @@ type InfoCache struct {
glue map[string][]net.IP
}
// NewInfoCache creates an InfoCache with an optional parent.
// Pass nil for a root-level cache with no parent.
func NewInfoCache(parent *InfoCache) *InfoCache {
return &InfoCache{
parent: parent,
@@ -23,6 +32,8 @@ func NewInfoCache(parent *InfoCache) *InfoCache {
}
}
// StoreNS records the nameserver names for zone in the local cache.
// Duplicate names within a zone are deduplicated.
func (c *InfoCache) StoreNS(zone string, nameservers []string) {
if len(nameservers) == 0 {
return
@@ -40,6 +51,8 @@ func (c *InfoCache) StoreNS(zone string, nameservers []string) {
c.mu.Unlock()
}
// LookupNS returns the cached nameserver names for zone,
// walking the parent chain when no local entry is found.
func (c *InfoCache) LookupNS(zone string) []string {
zone = normalize(zone)
if names := c.localNS(zone); len(names) > 0 {
@@ -63,6 +76,8 @@ func (c *InfoCache) localNS(zone string) []string {
return result
}
// StoreGlue records the IP addresses for a nameserver hostname in the local cache.
// Duplicate addresses are deduplicated.
func (c *InfoCache) StoreGlue(name string, addrs []net.IP) {
if len(addrs) == 0 {
return
@@ -80,6 +95,8 @@ func (c *InfoCache) StoreGlue(name string, addrs []net.IP) {
c.mu.Unlock()
}
// LookupGlue returns the cached IP addresses for a nameserver hostname,
// walking the parent chain when no local entry is found.
func (c *InfoCache) LookupGlue(name string) []net.IP {
name = normalize(name)
if addrs := c.localGlue(name); len(addrs) > 0 {
@@ -103,16 +120,20 @@ func (c *InfoCache) localGlue(name string) []net.IP {
return result
}
// Child creates a new InfoCache that inherits from c.
// The child reads from c when a local lookup misses, but never writes to c.
func (c *InfoCache) Child() *InfoCache {
return NewInfoCache(c)
}
// NSCount returns the number of zone→nameservers entries in the local cache.
func (c *InfoCache) NSCount() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.ns)
}
// GlueCount returns the number of nameserver→addresses entries in the local cache.
func (c *InfoCache) GlueCount() int {
c.mu.RLock()
defer c.mu.RUnlock()