// Package resolver provides iterative DNS resolution from root nameservers. // It traces the full delegation chain from IANA root servers through TLD // and domain nameservers, never relying on upstream recursive resolvers. package resolver import ( "context" "log/slog" "go.uber.org/fx" "sneak.berlin/go/dnswatcher/internal/logger" ) // Query status constants matching the state model. const ( StatusOK = "ok" StatusError = "error" StatusNXDomain = "nxdomain" StatusNoData = "nodata" ) // MaxCNAMEDepth is the maximum CNAME chain depth to follow. const MaxCNAMEDepth = 10 // Params contains dependencies for Resolver. type Params struct { fx.In Logger *logger.Logger } // NameserverResponse holds one nameserver's response for a query. type NameserverResponse struct { Nameserver string Records map[string][]string Status string Error string } // Resolver performs iterative DNS resolution from root servers. type Resolver struct { log *slog.Logger } // New creates a new Resolver instance for use with uber/fx. func New( _ fx.Lifecycle, params Params, ) (*Resolver, error) { return &Resolver{ log: params.Logger.Get(), }, nil } // NewFromLogger creates a Resolver directly from an slog.Logger, // useful for testing without the fx lifecycle. func NewFromLogger(log *slog.Logger) *Resolver { return &Resolver{log: log} } // FindAuthoritativeNameservers traces the delegation chain from // root servers to discover all authoritative nameservers for the // given domain. Returns the NS hostnames (e.g. ["ns1.example.com.", // "ns2.example.com."]). func (r *Resolver) FindAuthoritativeNameservers( _ context.Context, _ string, ) ([]string, error) { return nil, ErrNotImplemented } // QueryNameserver queries a specific authoritative nameserver for // all supported record types (A, AAAA, CNAME, MX, TXT, SRV, CAA, // NS) for the given hostname. Returns a NameserverResponse with // per-type record slices and a status indicating success or the // type of failure. func (r *Resolver) QueryNameserver( _ context.Context, _ string, _ string, ) (*NameserverResponse, error) { return nil, ErrNotImplemented } // QueryAllNameservers discovers the authoritative nameservers for // the hostname's parent domain, then queries each one independently. // Returns a map from nameserver hostname to its response. func (r *Resolver) QueryAllNameservers( _ context.Context, _ string, ) (map[string]*NameserverResponse, error) { return nil, ErrNotImplemented } // LookupNS returns the NS record set for a domain by performing // iterative resolution. This is used for domain (apex) monitoring. func (r *Resolver) LookupNS( _ context.Context, _ string, ) ([]string, error) { return nil, ErrNotImplemented } // ResolveIPAddresses resolves a hostname to all IPv4 and IPv6 // addresses by querying all authoritative nameservers and following // CNAME chains up to MaxCNAMEDepth. Returns a deduplicated list // of IP address strings. func (r *Resolver) ResolveIPAddresses( _ context.Context, _ string, ) ([]string, error) { return nil, ErrNotImplemented }