Domain Connect discovery: find the DNS provider's Domain Connect API for a domain, then fetch its settings.
Three steps, matching the canonical reference implementation:
- Compute the registrable domain (the zone) using the Public Suffix
List, so
rent.theirplace.co.ukresolves to the zonetheirplace.co.uk(notco.uk) and hostrent. This is correct for multi-label TLDs. - Look up the
TXTrecord at_domainconnect.<zone>. Its value is the host of the provider's Domain Connect API. The host is validated byDomainConnect.HostGuard(SSRF protection) before any request. GET https://<api-host>/v2/<zone>/settings(no redirects, short timeouts), validate the response, and decode it into aDomainConnect.Config.
The DNS resolver, address resolver (for the SSRF guard), and HTTP client are
all injectable for testing — see the options on discover/2.
Registrable zone only
Discovery uses the PSL registrable domain, matching the reference library. A Domain Connect record published on a delegated sub-zone (not the registrable domain) is not discovered. This is a deliberate limitation.
Summary
Functions
Discovers the Domain Connect configuration for domain.
Splits a domain into its registrable zone and the sub-host using the Public Suffix List.
Types
Functions
@spec discover( String.t(), keyword() ) :: {:ok, DomainConnect.Config.t()} | {:error, term()}
Discovers the Domain Connect configuration for domain.
Options
:resolver— a 1-arity fun taking a name (e.g."_domainconnect.example.com") and returning a list of TXT record strings. Defaults to a:inet_res-backed resolver.:address_resolver— passed toDomainConnect.HostGuard.check/2to resolve the API host's IPs for the SSRF guard.:req_options— keyword options merged into theReqrequest that fetches/settings(e.g.plug:forReq.Test).
Returns {:ok, %DomainConnect.Config{}} or {:error, reason} where reason is
one of :invalid_domain, :not_supported (no usable _domainconnect
record), :invalid_settings, {:unsafe_host, host_guard_reason},
{:settings_http_error, status}, or {:settings_transport_error, term}.
Splits a domain into its registrable zone and the sub-host using the Public Suffix List.
iex> DomainConnect.Discovery.registrable("rent.theirplace.co.uk")
{:ok, "theirplace.co.uk", "rent"}
iex> DomainConnect.Discovery.registrable("example.com")
{:ok, "example.com", nil}Returns {:error, :invalid_domain} if the input can't be parsed.