Repository: go-acme/lego
Pull request #2352 (2024-11-15 18:49:45)

chore: check DNSProvider interface
To avoid missing methods.


Patch:
diff --git a/providers/dns/acmedns/acmedns.go b/providers/dns/acmedns/acmedns.go
index b7ec3165..7ba7f08d 100644
--- a/providers/dns/acmedns/acmedns.go
+++ b/providers/dns/acmedns/acmedns.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 
 	"github.com/cpu/goacmedns"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 )
@@ -23,6 +24,8 @@ const (
 	EnvStoragePath = envNamespace + "STORAGE_PATH"
 )
 
+var _ challenge.Provider = (*DNSProvider)(nil)
+
 // acmeDNSClient is an interface describing the goacmedns.Client functions the DNSProvider uses.
 // It makes it easier for tests to shim a mock Client into the DNSProvider.
 type acmeDNSClient interface {
diff --git a/providers/dns/alidns/alidns.go b/providers/dns/alidns/alidns.go
index 803567e1..9129eef0 100644
--- a/providers/dns/alidns/alidns.go
+++ b/providers/dns/alidns/alidns.go
@@ -11,13 +11,12 @@ import (
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
 	"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"golang.org/x/net/idna"
 )
 
-const defaultRegionID = "cn-hangzhou"
-
 // Environment variables names.
 const (
 	envNamespace = "ALICLOUD_"
@@ -34,6 +33,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const defaultRegionID = "cn-hangzhou"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	RAMRole            string
diff --git a/providers/dns/allinkl/allinkl.go b/providers/dns/allinkl/allinkl.go
index aaaca844..b1a40ae6 100644
--- a/providers/dns/allinkl/allinkl.go
+++ b/providers/dns/allinkl/allinkl.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/allinkl/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Login              string
diff --git a/providers/dns/arvancloud/arvancloud.go b/providers/dns/arvancloud/arvancloud.go
index 759d1922..3dd4eee7 100644
--- a/providers/dns/arvancloud/arvancloud.go
+++ b/providers/dns/arvancloud/arvancloud.go
@@ -9,13 +9,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/arvancloud/internal"
 )
 
-const minTTL = 600
-
 // Environment variables names.
 const (
 	envNamespace = "ARVANCLOUD_"
@@ -28,6 +27,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 600
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/auroradns/auroradns.go b/providers/dns/auroradns/auroradns.go
index 2f759d4a..8a497ffa 100644
--- a/providers/dns/auroradns/auroradns.go
+++ b/providers/dns/auroradns/auroradns.go
@@ -7,13 +7,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/auroradns"
 )
 
-const defaultBaseURL = "https://api.auroradns.eu"
-
 // Environment variables names.
 const (
 	envNamespace = "AURORA_"
@@ -27,6 +26,10 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const defaultBaseURL = "https://api.auroradns.eu"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/autodns/autodns.go b/providers/dns/autodns/autodns.go
index 67b98d17..61f3005f 100644
--- a/providers/dns/autodns/autodns.go
+++ b/providers/dns/autodns/autodns.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/autodns/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Endpoint           *url.URL
diff --git a/providers/dns/azure/azure.go b/providers/dns/azure/azure.go
index bb5a741d..5702acd8 100644
--- a/providers/dns/azure/azure.go
+++ b/providers/dns/azure/azure.go
@@ -18,8 +18,6 @@ import (
 	"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
 )
 
-const defaultMetadataEndpoint = "http://169.254.169.254"
-
 // Environment variables names.
 const (
 	envNamespace = "AZURE_"
@@ -39,6 +37,10 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const defaultMetadataEndpoint = "http://169.254.169.254"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ZoneName string
diff --git a/providers/dns/azuredns/azuredns.go b/providers/dns/azuredns/azuredns.go
index 765bd073..dd591d92 100644
--- a/providers/dns/azuredns/azuredns.go
+++ b/providers/dns/azuredns/azuredns.go
@@ -51,6 +51,8 @@ const (
 	EnvGitHubOIDCRequestToken = "ACTIONS_ID_TOKEN_REQUEST_TOKEN"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ZoneName string
diff --git a/providers/dns/azuredns/private.go b/providers/dns/azuredns/private.go
index d31d20b0..c3d6cf35 100644
--- a/providers/dns/azuredns/private.go
+++ b/providers/dns/azuredns/private.go
@@ -12,9 +12,12 @@ import (
 	"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
 	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
 	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProviderPrivate)(nil)
+
 // DNSProviderPrivate implements the challenge.Provider interface for Azure Private Zone DNS.
 type DNSProviderPrivate struct {
 	config                *Config
diff --git a/providers/dns/azuredns/public.go b/providers/dns/azuredns/public.go
index abe26970..f6c00b2a 100644
--- a/providers/dns/azuredns/public.go
+++ b/providers/dns/azuredns/public.go
@@ -12,9 +12,12 @@ import (
 	"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
 	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
 	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProviderPublic)(nil)
+
 // DNSProviderPublic implements the challenge.Provider interface for Azure Public Zone DNS.
 type DNSProviderPublic struct {
 	config                *Config
diff --git a/providers/dns/bindman/bindman.go b/providers/dns/bindman/bindman.go
index 1ec39607..fbaddcbe 100644
--- a/providers/dns/bindman/bindman.go
+++ b/providers/dns/bindman/bindman.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/labbsr0x/bindman-dns-webhook/src/client"
@@ -23,6 +24,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	PropagationTimeout time.Duration
diff --git a/providers/dns/bluecat/bluecat.go b/providers/dns/bluecat/bluecat.go
index ad7add9f..8ba026f4 100644
--- a/providers/dns/bluecat/bluecat.go
+++ b/providers/dns/bluecat/bluecat.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -32,6 +33,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/brandit/brandit.go b/providers/dns/brandit/brandit.go
index 5d7b23d0..437d1642 100644
--- a/providers/dns/brandit/brandit.go
+++ b/providers/dns/brandit/brandit.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/brandit/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey      string
diff --git a/providers/dns/bunny/bunny.go b/providers/dns/bunny/bunny.go
index 2cf7ea54..63a5a01e 100644
--- a/providers/dns/bunny/bunny.go
+++ b/providers/dns/bunny/bunny.go
@@ -7,13 +7,12 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/bunny-go"
 )
 
-const minTTL = 60
-
 // Environment variables names.
 const (
 	envNamespace = "BUNNY_"
@@ -25,6 +24,10 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const minTTL = 60
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/checkdomain/checkdomain.go b/providers/dns/checkdomain/checkdomain.go
index 4f1e7c13..e2d7a05a 100644
--- a/providers/dns/checkdomain/checkdomain.go
+++ b/providers/dns/checkdomain/checkdomain.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/checkdomain/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Endpoint           *url.URL
diff --git a/providers/dns/civo/civo.go b/providers/dns/civo/civo.go
index 26bdc799..e2ee41bd 100644
--- a/providers/dns/civo/civo.go
+++ b/providers/dns/civo/civo.go
@@ -7,16 +7,11 @@ import (
 	"time"
 
 	"github.com/civo/civogo"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 )
 
-const (
-	minTTL                    = 600
-	defaultPollingInterval    = 30 * time.Second
-	defaultPropagationTimeout = 300 * time.Second
-)
-
 // Environment variables names.
 const (
 	envNamespace = "CIVO_"
@@ -28,6 +23,14 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const (
+	minTTL                    = 600
+	defaultPollingInterval    = 30 * time.Second
+	defaultPropagationTimeout = 300 * time.Second
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ProjectID          string
diff --git a/providers/dns/clouddns/clouddns.go b/providers/dns/clouddns/clouddns.go
index c3b13887..379dd3cf 100644
--- a/providers/dns/clouddns/clouddns.go
+++ b/providers/dns/clouddns/clouddns.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/clouddns/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the DNSProvider.
 type Config struct {
 	ClientID string
diff --git a/providers/dns/cloudflare/cloudflare.go b/providers/dns/cloudflare/cloudflare.go
index efdbd6e7..ded6150e 100644
--- a/providers/dns/cloudflare/cloudflare.go
+++ b/providers/dns/cloudflare/cloudflare.go
@@ -6,19 +6,45 @@ import (
 	"errors"
 	"fmt"
 	"net/http"
+	"strconv"
+	"strings"
 	"sync"
 	"time"
 
 	"github.com/cloudflare/cloudflare-go"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
 )
 
+// Environment variables names.
+const (
+	envNamespace = "CLOUDFLARE_"
+
+	EnvEmail        = envNamespace + "EMAIL"
+	EnvAPIKey       = envNamespace + "API_KEY"
+	EnvDNSAPIToken  = envNamespace + "DNS_API_TOKEN"
+	EnvZoneAPIToken = envNamespace + "ZONE_API_TOKEN"
+
+	EnvTTL                = envNamespace + "TTL"
+	EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
+	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
+	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
+)
+
+const (
+	altEnvNamespace = "CF_"
+
+	altEnvEmail = altEnvNamespace + "API_EMAIL"
+)
+
 const (
 	minTTL = 120
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AuthEmail string
@@ -36,11 +62,11 @@ type Config struct {
 // NewDefaultConfig returns a default configuration for the DNSProvider.
 func NewDefaultConfig() *Config {
 	return &Config{
-		TTL:                env.GetOrDefaultInt("CLOUDFLARE_TTL", minTTL),
-		PropagationTimeout: env.GetOrDefaultSecond("CLOUDFLARE_PROPAGATION_TIMEOUT", 2*time.Minute),
-		PollingInterval:    env.GetOrDefaultSecond("CLOUDFLARE_POLLING_INTERVAL", 2*time.Second),
+		TTL:                env.GetOneWithFallback(EnvTTL, minTTL, strconv.Atoi, altEnvName(EnvTTL)),
+		PropagationTimeout: env.GetOneWithFallback(EnvPropagationTimeout, 2*time.Minute, env.ParseSecond, altEnvName(EnvPropagationTimeout)),
+		PollingInterval:    env.GetOneWithFallback(EnvPollingInterval, 2*time.Second, env.ParseSecond, altEnvName(EnvPollingInterval)),
 		HTTPClient: &http.Client{
-			Timeout: env.GetOrDefaultSecond("CLOUDFLARE_HTTP_TIMEOUT", 30*time.Second),
+			Timeout: env.GetOneWithFallback(EnvHTTPTimeout, 30*time.Second, env.ParseSecond, altEnvName(EnvHTTPTimeout)),
 		},
 	}
 }
@@ -68,14 +94,14 @@ type DNSProvider struct {
 // in this case pass both CLOUDFLARE_ZONE_API_TOKEN and CLOUDFLARE_DNS_API_TOKEN accordingly.
 func NewDNSProvider() (*DNSProvider, error) {
 	values, err := env.GetWithFallback(
-		[]string{"CLOUDFLARE_EMAIL", "CF_API_EMAIL"},
-		[]string{"CLOUDFLARE_API_KEY", "CF_API_KEY"},
+		[]string{EnvEmail, altEnvEmail},
+		[]string{EnvAPIKey, altEnvName(EnvAPIKey)},
 	)
 	if err != nil {
 		var errT error
 		values, errT = env.GetWithFallback(
-			[]string{"CLOUDFLARE_DNS_API_TOKEN", "CF_DNS_API_TOKEN"},
-			[]string{"CLOUDFLARE_ZONE_API_TOKEN", "CF_ZONE_API_TOKEN", "CLOUDFLARE_DNS_API_TOKEN", "CF_DNS_API_TOKEN"},
+			[]string{EnvDNSAPIToken, altEnvName(EnvDNSAPIToken)},
+			[]string{EnvZoneAPIToken, altEnvName(EnvZoneAPIToken), EnvDNSAPIToken, altEnvName(EnvDNSAPIToken)},
 		)
 		if errT != nil {
 			//nolint:errorlint
@@ -84,10 +110,10 @@ func NewDNSProvider() (*DNSProvider, error) {
 	}
 
 	config := NewDefaultConfig()
-	config.AuthEmail = values["CLOUDFLARE_EMAIL"]
-	config.AuthKey = values["CLOUDFLARE_API_KEY"]
-	config.AuthToken = values["CLOUDFLARE_DNS_API_TOKEN"]
-	config.ZoneToken = values["CLOUDFLARE_ZONE_API_TOKEN"]
+	config.AuthEmail = values[EnvEmail]
+	config.AuthKey = values[EnvAPIKey]
+	config.AuthToken = values[EnvDNSAPIToken]
+	config.ZoneToken = values[EnvZoneAPIToken]
 
 	return NewDNSProviderConfig(config)
 }
@@ -189,3 +215,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 	return nil
 }
+
+func altEnvName(v string) string {
+	return strings.ReplaceAll(v, envNamespace, altEnvNamespace)
+}
diff --git a/providers/dns/cloudns/cloudns.go b/providers/dns/cloudns/cloudns.go
index 554e5416..ef6524c4 100644
--- a/providers/dns/cloudns/cloudns.go
+++ b/providers/dns/cloudns/cloudns.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AuthID             string
diff --git a/providers/dns/cloudru/cloudru.go b/providers/dns/cloudru/cloudru.go
index 68ad21b2..314c2044 100644
--- a/providers/dns/cloudru/cloudru.go
+++ b/providers/dns/cloudru/cloudru.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/cloudru/internal"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ServiceInstanceID string
diff --git a/providers/dns/conoha/conoha.go b/providers/dns/conoha/conoha.go
index 32755b9f..aa6c68ce 100644
--- a/providers/dns/conoha/conoha.go
+++ b/providers/dns/conoha/conoha.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/conoha/internal"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Region             string
diff --git a/providers/dns/constellix/constellix.go b/providers/dns/constellix/constellix.go
index a7e81371..f981b497 100644
--- a/providers/dns/constellix/constellix.go
+++ b/providers/dns/constellix/constellix.go
@@ -10,6 +10,7 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/constellix/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/corenetworks/corenetworks.go b/providers/dns/corenetworks/corenetworks.go
index 43b2f47b..119b3c16 100644
--- a/providers/dns/corenetworks/corenetworks.go
+++ b/providers/dns/corenetworks/corenetworks.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/corenetworks/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Login              string
diff --git a/providers/dns/cpanel/cpanel.go b/providers/dns/cpanel/cpanel.go
index bb025c2a..4c80e4db 100644
--- a/providers/dns/cpanel/cpanel.go
+++ b/providers/dns/cpanel/cpanel.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/cpanel/internal/cpanel"
@@ -33,6 +34,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 type apiClient interface {
 	FetchZoneInformation(ctx context.Context, domain string) ([]shared.ZoneRecord, error)
 	AddRecord(ctx context.Context, serial uint32, domain string, record shared.Record) (*shared.ZoneSerial, error)
diff --git a/providers/dns/derak/derak.go b/providers/dns/derak/derak.go
index 28262fb0..6e726620 100644
--- a/providers/dns/derak/derak.go
+++ b/providers/dns/derak/derak.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/derak/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/desec/desec.go b/providers/dns/desec/desec.go
index a8aee6ac..9d1e20e5 100644
--- a/providers/dns/desec/desec.go
+++ b/providers/dns/desec/desec.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/desec"
@@ -30,6 +31,8 @@ const (
 // https://desec.readthedocs.io/_/downloads/en/latest/pdf/
 const defaultTTL int = 3600
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/designate/designate.go b/providers/dns/designate/designate.go
index 8b712b5a..e2a5721c 100644
--- a/providers/dns/designate/designate.go
+++ b/providers/dns/designate/designate.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/gophercloud/gophercloud"
@@ -44,6 +45,8 @@ const (
 	EnvCloud         = envNamespaceClient + "CLOUD"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ZoneName           string
diff --git a/providers/dns/digitalocean/digitalocean.go b/providers/dns/digitalocean/digitalocean.go
index 4ef8c061..976b1f2e 100644
--- a/providers/dns/digitalocean/digitalocean.go
+++ b/providers/dns/digitalocean/digitalocean.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/digitalocean/internal"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/directadmin/directadmin.go b/providers/dns/directadmin/directadmin.go
index 88986072..de9b1494 100644
--- a/providers/dns/directadmin/directadmin.go
+++ b/providers/dns/directadmin/directadmin.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/directadmin/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL  string
diff --git a/providers/dns/dnsimple/dnsimple.go b/providers/dns/dnsimple/dnsimple.go
index 0c1d3067..db80eb80 100644
--- a/providers/dns/dnsimple/dnsimple.go
+++ b/providers/dns/dnsimple/dnsimple.go
@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/dnsimple/dnsimple-go/dnsimple"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -28,6 +29,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Debug              bool
diff --git a/providers/dns/dnsmadeeasy/dnsmadeeasy.go b/providers/dns/dnsmadeeasy/dnsmadeeasy.go
index 7f4ca2af..e4e77726 100644
--- a/providers/dns/dnsmadeeasy/dnsmadeeasy.go
+++ b/providers/dns/dnsmadeeasy/dnsmadeeasy.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/dnsmadeeasy/internal"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/dnspod/dnspod.go b/providers/dns/dnspod/dnspod.go
index 5f8e8488..ab8f20c8 100644
--- a/providers/dns/dnspod/dnspod.go
+++ b/providers/dns/dnspod/dnspod.go
@@ -8,6 +8,7 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/dnspod-go"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	LoginToken         string
diff --git a/providers/dns/dode/dode.go b/providers/dns/dode/dode.go
index 04393fb0..9f307f04 100644
--- a/providers/dns/dode/dode.go
+++ b/providers/dns/dode/dode.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/dode/internal"
@@ -25,6 +26,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/domeneshop/domeneshop.go b/providers/dns/domeneshop/domeneshop.go
index d074ba53..c194f560 100644
--- a/providers/dns/domeneshop/domeneshop.go
+++ b/providers/dns/domeneshop/domeneshop.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/domeneshop/internal"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIToken           string
diff --git a/providers/dns/dreamhost/dreamhost.go b/providers/dns/dreamhost/dreamhost.go
index 8f0c850d..5b4960ee 100644
--- a/providers/dns/dreamhost/dreamhost.go
+++ b/providers/dns/dreamhost/dreamhost.go
@@ -10,6 +10,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/dreamhost/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/duckdns/duckdns.go b/providers/dns/duckdns/duckdns.go
index 8cb82aed..687f5bba 100644
--- a/providers/dns/duckdns/duckdns.go
+++ b/providers/dns/duckdns/duckdns.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/duckdns/internal"
@@ -26,6 +27,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/dyn/dyn.go b/providers/dns/dyn/dyn.go
index 3435110e..627626df 100644
--- a/providers/dns/dyn/dyn.go
+++ b/providers/dns/dyn/dyn.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/dyn/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	CustomerName       string
diff --git a/providers/dns/dynu/dynu.go b/providers/dns/dynu/dynu.go
index d0c396a2..af602ddf 100644
--- a/providers/dns/dynu/dynu.go
+++ b/providers/dns/dynu/dynu.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/dynu/internal"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/easydns/easydns.go b/providers/dns/easydns/easydns.go
index 20ad2754..7e5e219c 100644
--- a/providers/dns/easydns/easydns.go
+++ b/providers/dns/easydns/easydns.go
@@ -12,6 +12,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/easydns/internal"
@@ -32,6 +33,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Endpoint           *url.URL
diff --git a/providers/dns/edgedns/edgedns.go b/providers/dns/edgedns/edgedns.go
index 263ba0c3..d44d2eaf 100644
--- a/providers/dns/edgedns/edgedns.go
+++ b/providers/dns/edgedns/edgedns.go
@@ -10,6 +10,7 @@ import (
 
 	configdns "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v2"
 	"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -39,6 +40,8 @@ const (
 
 const maxBody = 131072
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	edgegrid.Config
diff --git a/providers/dns/efficientip/efficientip.go b/providers/dns/efficientip/efficientip.go
index 6d639bce..15fa579e 100644
--- a/providers/dns/efficientip/efficientip.go
+++ b/providers/dns/efficientip/efficientip.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/efficientip/internal"
@@ -30,6 +31,8 @@ const (
 	EnvInsecureSkipVerify = envNamespace + "INSECURE_SKIP_VERIFY"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/epik/epik.go b/providers/dns/epik/epik.go
index 4d4fb8c7..58390faa 100644
--- a/providers/dns/epik/epik.go
+++ b/providers/dns/epik/epik.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/epik/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Signature          string
diff --git a/providers/dns/exec/exec.go b/providers/dns/exec/exec.go
index 23fdaf38..9f000b80 100644
--- a/providers/dns/exec/exec.go
+++ b/providers/dns/exec/exec.go
@@ -10,6 +10,7 @@ import (
 	"os/exec"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -27,6 +28,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config Provider configuration.
 type Config struct {
 	Program            string
diff --git a/providers/dns/exoscale/exoscale.go b/providers/dns/exoscale/exoscale.go
index c9402a75..4038ee4d 100644
--- a/providers/dns/exoscale/exoscale.go
+++ b/providers/dns/exoscale/exoscale.go
@@ -10,6 +10,7 @@ import (
 
 	egoscale "github.com/exoscale/egoscale/v3"
 	"github.com/exoscale/egoscale/v3/credentials"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/freemyip/freemyip.go b/providers/dns/freemyip/freemyip.go
index 18fcb056..7613f2b8 100644
--- a/providers/dns/freemyip/freemyip.go
+++ b/providers/dns/freemyip/freemyip.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/freemyip"
@@ -26,6 +27,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/gandi/gandi.go b/providers/dns/gandi/gandi.go
index 93e94f27..dd662217 100644
--- a/providers/dns/gandi/gandi.go
+++ b/providers/dns/gandi/gandi.go
@@ -9,16 +9,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/gandi/internal"
 )
 
-// Gandi API reference:       http://doc.rpc.gandi.net/index.html
-// Gandi API domain examples: http://doc.rpc.gandi.net/domain/faq.html
-
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "GANDI_"
@@ -31,6 +27,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/gandiv5/gandiv5.go b/providers/dns/gandiv5/gandiv5.go
index 8b342592..3c35245d 100644
--- a/providers/dns/gandiv5/gandiv5.go
+++ b/providers/dns/gandiv5/gandiv5.go
@@ -10,16 +10,13 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/gandiv5/internal"
 )
 
-// Gandi API reference:       http://doc.livedns.gandi.net/
-
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "GANDIV5_"
@@ -33,6 +30,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // inProgressInfo contains information about an in-progress challenge.
 type inProgressInfo struct {
 	fieldName string
diff --git a/providers/dns/gcloud/googlecloud.go b/providers/dns/gcloud/googlecloud.go
index bec094d1..99c716b6 100644
--- a/providers/dns/gcloud/googlecloud.go
+++ b/providers/dns/gcloud/googlecloud.go
@@ -11,6 +11,7 @@ import (
 	"time"
 
 	"cloud.google.com/go/compute/metadata"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -22,10 +23,6 @@ import (
 	"google.golang.org/api/option"
 )
 
-const (
-	changeStatusDone = "done"
-)
-
 // Environment variables names.
 const (
 	envNamespace = "GCE_"
@@ -41,6 +38,10 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const changeStatusDone = "done"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Debug              bool
diff --git a/providers/dns/gcore/gcore.go b/providers/dns/gcore/gcore.go
index fe427647..646c5ab1 100644
--- a/providers/dns/gcore/gcore.go
+++ b/providers/dns/gcore/gcore.go
@@ -8,16 +8,12 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/gcore/internal"
 )
 
-const (
-	defaultPropagationTimeout = 360 * time.Second
-	defaultPollingInterval    = 20 * time.Second
-)
-
 // Environment variables names.
 const (
 	envNamespace = "GCORE_"
@@ -30,6 +26,13 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const (
+	defaultPropagationTimeout = 360 * time.Second
+	defaultPollingInterval    = 20 * time.Second
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config for DNSProvider.
 type Config struct {
 	APIToken           string
diff --git a/providers/dns/glesys/glesys.go b/providers/dns/glesys/glesys.go
index c25b693c..4b0d545e 100644
--- a/providers/dns/glesys/glesys.go
+++ b/providers/dns/glesys/glesys.go
@@ -9,13 +9,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/glesys/internal"
 )
 
-const minTTL = 60
-
 // Environment variables names.
 const (
 	envNamespace = "GLESYS_"
@@ -29,6 +28,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 60
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIUser            string
diff --git a/providers/dns/godaddy/godaddy.go b/providers/dns/godaddy/godaddy.go
index 7a80ac93..bc0f4233 100644
--- a/providers/dns/godaddy/godaddy.go
+++ b/providers/dns/godaddy/godaddy.go
@@ -8,13 +8,12 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/godaddy/internal"
 )
 
-const minTTL = 600
-
 // Environment variables names.
 const (
 	envNamespace = "GODADDY_"
@@ -28,6 +27,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 600
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/googledomains/googledomains.go b/providers/dns/googledomains/googledomains.go
index a87895c6..93392914 100644
--- a/providers/dns/googledomains/googledomains.go
+++ b/providers/dns/googledomains/googledomains.go
@@ -25,8 +25,7 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
-// static compile-time check on interface implementation.
-var _ challenge.Provider = &DNSProvider{}
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
 
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
diff --git a/providers/dns/hetzner/hetzner.go b/providers/dns/hetzner/hetzner.go
index 5b2112d7..e5c5ca26 100644
--- a/providers/dns/hetzner/hetzner.go
+++ b/providers/dns/hetzner/hetzner.go
@@ -8,13 +8,12 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/hetzner/internal"
 )
 
-const minTTL = 60
-
 // Environment variables names.
 const (
 	envNamespace = "HETZNER_"
@@ -27,6 +26,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 60
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/hostingde/hostingde.go b/providers/dns/hostingde/hostingde.go
index 3b63bbfb..67c4661b 100644
--- a/providers/dns/hostingde/hostingde.go
+++ b/providers/dns/hostingde/hostingde.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/hostingde"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/hosttech/hosttech.go b/providers/dns/hosttech/hosttech.go
index 94a6a079..22d3be7b 100644
--- a/providers/dns/hosttech/hosttech.go
+++ b/providers/dns/hosttech/hosttech.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/hosttech/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/httpnet/httpnet.go b/providers/dns/httpnet/httpnet.go
index 69f22e4b..41f4ffbf 100644
--- a/providers/dns/httpnet/httpnet.go
+++ b/providers/dns/httpnet/httpnet.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/hostingde"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/httpreq/httpreq.go b/providers/dns/httpreq/httpreq.go
index 81b3a698..8f8311e0 100644
--- a/providers/dns/httpreq/httpreq.go
+++ b/providers/dns/httpreq/httpreq.go
@@ -11,6 +11,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 type message struct {
 	FQDN  string `json:"fqdn"`
 	Value string `json:"value"`
diff --git a/providers/dns/huaweicloud/huaweicloud.go b/providers/dns/huaweicloud/huaweicloud.go
index 7f32f76d..9d20c27a 100644
--- a/providers/dns/huaweicloud/huaweicloud.go
+++ b/providers/dns/huaweicloud/huaweicloud.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/platform/wait"
@@ -33,6 +34,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccessKeyID     string
diff --git a/providers/dns/hurricane/hurricane.go b/providers/dns/hurricane/hurricane.go
index d17ceb89..e2054d38 100644
--- a/providers/dns/hurricane/hurricane.go
+++ b/providers/dns/hurricane/hurricane.go
@@ -8,6 +8,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/hurricane/internal"
@@ -25,6 +26,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Credentials        map[string]string
diff --git a/providers/dns/hyperone/hyperone.go b/providers/dns/hyperone/hyperone.go
index 8578b5c5..890f9f62 100644
--- a/providers/dns/hyperone/hyperone.go
+++ b/providers/dns/hyperone/hyperone.go
@@ -9,6 +9,7 @@ import (
 	"path/filepath"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/hyperone/internal"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIEndpoint      string
diff --git a/providers/dns/ibmcloud/ibmcloud.go b/providers/dns/ibmcloud/ibmcloud.go
index 82d817f1..81dec8e8 100644
--- a/providers/dns/ibmcloud/ibmcloud.go
+++ b/providers/dns/ibmcloud/ibmcloud.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/ibmcloud/internal"
@@ -32,6 +33,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/iij/iij.go b/providers/dns/iij/iij.go
index f5d0fdf9..9beb411e 100644
--- a/providers/dns/iij/iij.go
+++ b/providers/dns/iij/iij.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/iij/doapi"
@@ -28,6 +29,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccessKey          string
diff --git a/providers/dns/iijdpf/iijdpf.go b/providers/dns/iijdpf/iijdpf.go
index a703aeaf..2a626e88 100644
--- a/providers/dns/iijdpf/iijdpf.go
+++ b/providers/dns/iijdpf/iijdpf.go
@@ -28,6 +28,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token       string
@@ -49,8 +51,6 @@ func NewDefaultConfig() *Config {
 	}
 }
 
-var _ challenge.Provider = &DNSProvider{}
-
 // DNSProvider implements the challenge.Provider interface.
 type DNSProvider struct {
 	client dpfapi.ClientInterface
diff --git a/providers/dns/infoblox/infoblox.go b/providers/dns/infoblox/infoblox.go
index 87a443e4..6aefd0bc 100644
--- a/providers/dns/infoblox/infoblox.go
+++ b/providers/dns/infoblox/infoblox.go
@@ -8,6 +8,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -34,6 +35,8 @@ const (
 
 const defaultPoolConnections = 10
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	// Host is the URL of the grid manager.
diff --git a/providers/dns/infomaniak/infomaniak.go b/providers/dns/infomaniak/infomaniak.go
index 53d98c4f..84f49421 100644
--- a/providers/dns/infomaniak/infomaniak.go
+++ b/providers/dns/infomaniak/infomaniak.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/infomaniak/internal"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIEndpoint        string
diff --git a/providers/dns/internetbs/internetbs.go b/providers/dns/internetbs/internetbs.go
index 89b33eae..9d6c1767 100644
--- a/providers/dns/internetbs/internetbs.go
+++ b/providers/dns/internetbs/internetbs.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internetbs/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/inwx/inwx.go b/providers/dns/inwx/inwx.go
index dc26362f..cefea832 100644
--- a/providers/dns/inwx/inwx.go
+++ b/providers/dns/inwx/inwx.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -27,6 +28,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/ionos/ionos.go b/providers/dns/ionos/ionos.go
index fc322c89..d12fd7f0 100644
--- a/providers/dns/ionos/ionos.go
+++ b/providers/dns/ionos/ionos.go
@@ -10,13 +10,12 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/ionos/internal"
 )
 
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "IONOS_"
@@ -29,6 +28,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/ipv64/ipv64.go b/providers/dns/ipv64/ipv64.go
index 578614bc..6e8d1c5b 100644
--- a/providers/dns/ipv64/ipv64.go
+++ b/providers/dns/ipv64/ipv64.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/ipv64/internal"
@@ -24,9 +25,10 @@ const (
 	EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
-	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL" // Deprecated: unused, will be removed in v5.
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/iwantmyname/iwantmyname.go b/providers/dns/iwantmyname/iwantmyname.go
index e828446a..2b53377e 100644
--- a/providers/dns/iwantmyname/iwantmyname.go
+++ b/providers/dns/iwantmyname/iwantmyname.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/iwantmyname/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/joker/provider_dmapi.go b/providers/dns/joker/provider_dmapi.go
index ec85d570..5c623467 100644
--- a/providers/dns/joker/provider_dmapi.go
+++ b/providers/dns/joker/provider_dmapi.go
@@ -6,12 +6,15 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/joker/internal/dmapi"
 )
 
+var _ challenge.ProviderTimeout = (*dmapiProvider)(nil)
+
 // dmapiProvider implements the challenge.Provider interface.
 type dmapiProvider struct {
 	config *Config
diff --git a/providers/dns/joker/provider_svc.go b/providers/dns/joker/provider_svc.go
index c9edfded..991772fe 100644
--- a/providers/dns/joker/provider_svc.go
+++ b/providers/dns/joker/provider_svc.go
@@ -6,11 +6,14 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/joker/internal/svc"
 )
 
+var _ challenge.ProviderTimeout = (*svcProvider)(nil)
+
 // svcProvider implements the challenge.Provider interface.
 type svcProvider struct {
 	config *Config
diff --git a/providers/dns/liara/liara.go b/providers/dns/liara/liara.go
index cb4ab7c8..a0437b0e 100644
--- a/providers/dns/liara/liara.go
+++ b/providers/dns/liara/liara.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -16,11 +17,6 @@ import (
 	"github.com/hashicorp/go-retryablehttp"
 )
 
-const (
-	minTTL = 120
-	maxTTL = 432000
-)
-
 // Environment variables names.
 const (
 	envNamespace = "LIARA_"
@@ -33,6 +29,13 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const (
+	minTTL = 120
+	maxTTL = 432000
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/lightsail/lightsail.go b/providers/dns/lightsail/lightsail.go
index 125b1aa6..d07b5505 100644
--- a/providers/dns/lightsail/lightsail.go
+++ b/providers/dns/lightsail/lightsail.go
@@ -14,14 +14,11 @@ import (
 	awsconfig "github.com/aws/aws-sdk-go-v2/config"
 	"github.com/aws/aws-sdk-go-v2/service/lightsail"
 	awstypes "github.com/aws/aws-sdk-go-v2/service/lightsail/types"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 )
 
-const (
-	maxRetries = 5
-)
-
 // Environment variables names.
 const (
 	envNamespace = "LIGHTSAIL_"
@@ -33,6 +30,10 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const maxRetries = 5
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	DNSZone            string
diff --git a/providers/dns/limacity/limacity.go b/providers/dns/limacity/limacity.go
index a999f564..ef2c6950 100644
--- a/providers/dns/limacity/limacity.go
+++ b/providers/dns/limacity/limacity.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/limacity/internal"
@@ -29,6 +30,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/linode/linode.go b/providers/dns/linode/linode.go
index f9d77ebc..841e24c6 100644
--- a/providers/dns/linode/linode.go
+++ b/providers/dns/linode/linode.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -16,12 +17,6 @@ import (
 	"golang.org/x/oauth2"
 )
 
-const (
-	minTTL             = 300
-	dnsUpdateFreqMins  = 15
-	dnsUpdateFudgeSecs = 120
-)
-
 // Environment variables names.
 const (
 	envNamespace = "LINODE_"
@@ -34,6 +29,14 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const (
+	minTTL             = 300
+	dnsUpdateFreqMins  = 15
+	dnsUpdateFudgeSecs = 120
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/liquidweb/liquidweb.go b/providers/dns/liquidweb/liquidweb.go
index c7fd9eeb..76f96512 100644
--- a/providers/dns/liquidweb/liquidweb.go
+++ b/providers/dns/liquidweb/liquidweb.go
@@ -10,14 +10,13 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	lw "github.com/liquidweb/liquidweb-go/client"
 	"github.com/liquidweb/liquidweb-go/network"
 )
 
-const defaultBaseURL = "https://api.liquidweb.com"
-
 // Environment variables names.
 const (
 	envNamespace    = "LIQUID_WEB_"
@@ -34,6 +33,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const defaultBaseURL = "https://api.liquidweb.com"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/loopia/loopia.go b/providers/dns/loopia/loopia.go
index 582a247f..34d4374f 100644
--- a/providers/dns/loopia/loopia.go
+++ b/providers/dns/loopia/loopia.go
@@ -9,13 +9,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/loopia/internal"
 )
 
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "LOOPIA_"
@@ -30,6 +29,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 type dnsClient interface {
 	AddTXTRecord(ctx context.Context, domain string, subdomain string, ttl int, value string) error
 	RemoveTXTRecord(ctx context.Context, domain string, subdomain string, recordID int) error
diff --git a/providers/dns/luadns/luadns.go b/providers/dns/luadns/luadns.go
index 97261e15..ef0a9b7d 100644
--- a/providers/dns/luadns/luadns.go
+++ b/providers/dns/luadns/luadns.go
@@ -10,13 +10,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/luadns/internal"
 )
 
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "LUADNS_"
@@ -30,6 +29,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIUsername        string
diff --git a/providers/dns/mailinabox/mailinabox.go b/providers/dns/mailinabox/mailinabox.go
index 4d366379..3ea8a9f2 100644
--- a/providers/dns/mailinabox/mailinabox.go
+++ b/providers/dns/mailinabox/mailinabox.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/mailinabox"
@@ -24,6 +25,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Email              string
diff --git a/providers/dns/metaname/metaname.go b/providers/dns/metaname/metaname.go
index ab5a4dff..9b8c41de 100644
--- a/providers/dns/metaname/metaname.go
+++ b/providers/dns/metaname/metaname.go
@@ -8,6 +8,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nzdjb/go-metaname"
@@ -25,6 +26,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccountReference   string
diff --git a/providers/dns/mijnhost/mijnhost.go b/providers/dns/mijnhost/mijnhost.go
index 4d2cc1b3..32aadfb2 100644
--- a/providers/dns/mijnhost/mijnhost.go
+++ b/providers/dns/mijnhost/mijnhost.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/mijnhost/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/mittwald/mittwald.go b/providers/dns/mittwald/mittwald.go
index 66aafffb..47c62be5 100644
--- a/providers/dns/mittwald/mittwald.go
+++ b/providers/dns/mittwald/mittwald.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/mittwald/internal"
@@ -30,6 +31,8 @@ const (
 
 const minTTL = 300
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/mydnsjp/mydnsjp.go b/providers/dns/mydnsjp/mydnsjp.go
index beaaf49a..ec1aca35 100644
--- a/providers/dns/mydnsjp/mydnsjp.go
+++ b/providers/dns/mydnsjp/mydnsjp.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/mydnsjp/internal"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	MasterID           string
diff --git a/providers/dns/mythicbeasts/mythicbeasts.go b/providers/dns/mythicbeasts/mythicbeasts.go
index a23ff570..ae8f72d3 100644
--- a/providers/dns/mythicbeasts/mythicbeasts.go
+++ b/providers/dns/mythicbeasts/mythicbeasts.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/mythicbeasts/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	UserName           string
diff --git a/providers/dns/namecheap/namecheap.go b/providers/dns/namecheap/namecheap.go
index c4d9c069..f410fa5a 100644
--- a/providers/dns/namecheap/namecheap.go
+++ b/providers/dns/namecheap/namecheap.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -45,47 +46,7 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
-// A challenge represents all the data needed to specify a dns-01 challenge to lets-encrypt.
-type challenge struct {
-	domain   string
-	key      string
-	keyFqdn  string
-	keyValue string
-	tld      string
-	sld      string
-	host     string
-}
-
-// newChallenge builds a challenge record from a domain name and a challenge authentication key.
-func newChallenge(domain, keyAuth string) (*challenge, error) {
-	domain = dns01.UnFqdn(domain)
-
-	tld, _ := publicsuffix.PublicSuffix(domain)
-	if tld == domain {
-		return nil, fmt.Errorf("invalid domain name %q", domain)
-	}
-
-	parts := strings.Split(domain, ".")
-	longest := len(parts) - strings.Count(tld, ".") - 1
-	sld := parts[longest-1]
-
-	var host string
-	if longest >= 1 {
-		host = strings.Join(parts[:longest-1], ".")
-	}
-
-	info := dns01.GetChallengeInfo(domain, keyAuth)
-
-	return &challenge{
-		domain:   domain,
-		key:      "_acme-challenge." + host,
-		keyFqdn:  info.EffectiveFQDN,
-		keyValue: info.Value,
-		tld:      tld,
-		sld:      sld,
-		host:     host,
-	}, nil
-}
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
 
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
@@ -178,22 +139,22 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 // Present installs a TXT record for the DNS challenge.
 func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	// TODO(ldez) replace domain by FQDN to follow CNAME.
-	ch, err := newChallenge(domain, keyAuth)
+	pr, err := newPseudoRecord(domain, keyAuth)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
 
 	ctx := context.Background()
 
-	records, err := d.client.GetHosts(ctx, ch.sld, ch.tld)
+	records, err := d.client.GetHosts(ctx, pr.sld, pr.tld)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
 
 	record := internal.Record{
-		Name:    ch.key,
+		Name:    pr.key,
 		Type:    "TXT",
-		Address: ch.keyValue,
+		Address: pr.keyValue,
 		MXPref:  "10",
 		TTL:     strconv.Itoa(d.config.TTL),
 	}
@@ -206,7 +167,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 		}
 	}
 
-	err = d.client.SetHosts(ctx, ch.sld, ch.tld, records)
+	err = d.client.SetHosts(ctx, pr.sld, pr.tld, records)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
@@ -216,14 +177,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 // CleanUp removes a TXT record used for a previous DNS challenge.
 func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	// TODO(ldez) replace domain by FQDN to follow CNAME.
-	ch, err := newChallenge(domain, keyAuth)
+	pr, err := newPseudoRecord(domain, keyAuth)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
 
 	ctx := context.Background()
 
-	records, err := d.client.GetHosts(ctx, ch.sld, ch.tld)
+	records, err := d.client.GetHosts(ctx, pr.sld, pr.tld)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
@@ -232,7 +193,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	var found bool
 	var newRecords []internal.Record
 	for _, h := range records {
-		if h.Name == ch.key && h.Type == "TXT" {
+		if h.Name == pr.key && h.Type == "TXT" {
 			found = true
 		} else {
 			newRecords = append(newRecords, h)
@@ -243,9 +204,51 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		return nil
 	}
 
-	err = d.client.SetHosts(ctx, ch.sld, ch.tld, newRecords)
+	err = d.client.SetHosts(ctx, pr.sld, pr.tld, newRecords)
 	if err != nil {
 		return fmt.Errorf("namecheap: %w", err)
 	}
 	return nil
 }
+
+// A pseudoRecord represents all the data needed to specify a dns-01 challenge to lets-encrypt.
+type pseudoRecord struct {
+	domain   string
+	key      string
+	keyFqdn  string
+	keyValue string
+	tld      string
+	sld      string
+	host     string
+}
+
+// newPseudoRecord builds a challenge record from a domain name and a challenge authentication key.
+func newPseudoRecord(domain, keyAuth string) (*pseudoRecord, error) {
+	domain = dns01.UnFqdn(domain)
+
+	tld, _ := publicsuffix.PublicSuffix(domain)
+	if tld == domain {
+		return nil, fmt.Errorf("invalid domain name %q", domain)
+	}
+
+	parts := strings.Split(domain, ".")
+	longest := len(parts) - strings.Count(tld, ".") - 1
+	sld := parts[longest-1]
+
+	var host string
+	if longest >= 1 {
+		host = strings.Join(parts[:longest-1], ".")
+	}
+
+	info := dns01.GetChallengeInfo(domain, keyAuth)
+
+	return &pseudoRecord{
+		domain:   domain,
+		key:      "_acme-challenge." + host,
+		keyFqdn:  info.EffectiveFQDN,
+		keyValue: info.Value,
+		tld:      tld,
+		sld:      sld,
+		host:     host,
+	}, nil
+}
diff --git a/providers/dns/namedotcom/namedotcom.go b/providers/dns/namedotcom/namedotcom.go
index e49a15a9..5b2bbaf2 100644
--- a/providers/dns/namedotcom/namedotcom.go
+++ b/providers/dns/namedotcom/namedotcom.go
@@ -7,14 +7,12 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/namedotcom/go/namecom"
 )
 
-// according to https://www.name.com/api-docs/DNS#CreateRecord
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "NAMECOM_"
@@ -29,6 +27,11 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+// according to https://www.name.com/api-docs/DNS#CreateRecord
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/namesilo/namesilo.go b/providers/dns/namesilo/namesilo.go
index 450c3d68..f76c8549 100644
--- a/providers/dns/namesilo/namesilo.go
+++ b/providers/dns/namesilo/namesilo.go
@@ -6,16 +6,12 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/namesilo"
 )
 
-const (
-	defaultTTL = 3600
-	maxTTL     = 2592000
-)
-
 // Environment variables names.
 const (
 	envNamespace = "NAMESILO_"
@@ -27,6 +23,13 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const (
+	defaultTTL = 3600
+	maxTTL     = 2592000
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/nearlyfreespeech/nearlyfreespeech.go b/providers/dns/nearlyfreespeech/nearlyfreespeech.go
index 8f94e091..464ac35d 100644
--- a/providers/dns/nearlyfreespeech/nearlyfreespeech.go
+++ b/providers/dns/nearlyfreespeech/nearlyfreespeech.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/nearlyfreespeech/internal"
@@ -27,6 +28,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/netcup/netcup.go b/providers/dns/netcup/netcup.go
index a8fc8b17..014e09a1 100644
--- a/providers/dns/netcup/netcup.go
+++ b/providers/dns/netcup/netcup.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Key                string
diff --git a/providers/dns/netlify/netlify.go b/providers/dns/netlify/netlify.go
index 1a65e330..1d4c78f4 100644
--- a/providers/dns/netlify/netlify.go
+++ b/providers/dns/netlify/netlify.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/netlify/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/nicmanager/nicmanager.go b/providers/dns/nicmanager/nicmanager.go
index 5f7eaff6..f9307d8c 100644
--- a/providers/dns/nicmanager/nicmanager.go
+++ b/providers/dns/nicmanager/nicmanager.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/nicmanager/internal"
@@ -33,6 +34,8 @@ const (
 
 const minTTL = 900
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Login     string
diff --git a/providers/dns/nifcloud/nifcloud.go b/providers/dns/nifcloud/nifcloud.go
index b059e562..e73333c5 100644
--- a/providers/dns/nifcloud/nifcloud.go
+++ b/providers/dns/nifcloud/nifcloud.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/platform/wait"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/njalla/njalla.go b/providers/dns/njalla/njalla.go
index fe23e8d6..b08ce69d 100644
--- a/providers/dns/njalla/njalla.go
+++ b/providers/dns/njalla/njalla.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/njalla/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/nodion/nodion.go b/providers/dns/nodion/nodion.go
index e1ce72e8..1fdc8b87 100644
--- a/providers/dns/nodion/nodion.go
+++ b/providers/dns/nodion/nodion.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/nodion"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIToken string
diff --git a/providers/dns/ns1/ns1.go b/providers/dns/ns1/ns1.go
index ffa4b1b7..c3bf168c 100644
--- a/providers/dns/ns1/ns1.go
+++ b/providers/dns/ns1/ns1.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/oraclecloud/oraclecloud.go b/providers/dns/oraclecloud/oraclecloud.go
index a5561381..535c691b 100644
--- a/providers/dns/oraclecloud/oraclecloud.go
+++ b/providers/dns/oraclecloud/oraclecloud.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/oracle/oci-go-sdk/v65/common"
@@ -33,6 +34,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	CompartmentID      string
diff --git a/providers/dns/otc/otc.go b/providers/dns/otc/otc.go
index f2526b87..3bb11cec 100644
--- a/providers/dns/otc/otc.go
+++ b/providers/dns/otc/otc.go
@@ -9,16 +9,12 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/otc/internal"
 )
 
-const defaultIdentityEndpoint = "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens"
-
-// minTTL 300 is otc minimum value for TTL.
-const minTTL = 300
-
 // Environment variables names.
 const (
 	envNamespace = "OTC_"
@@ -36,6 +32,13 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+const defaultIdentityEndpoint = "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens"
+
+// minTTL 300 is otc minimum value for TTL.
+const minTTL = 300
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	IdentityEndpoint   string
diff --git a/providers/dns/ovh/ovh.go b/providers/dns/ovh/ovh.go
index c86d6129..547a1a47 100644
--- a/providers/dns/ovh/ovh.go
+++ b/providers/dns/ovh/ovh.go
@@ -8,6 +8,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -46,6 +47,8 @@ const (
 // EnvAccessToken Authenticate using Access Token client.
 const EnvAccessToken = envNamespace + "ACCESS_TOKEN"
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Record a DNS record.
 type Record struct {
 	ID        int64  `json:"id,omitempty"`
diff --git a/providers/dns/pdns/pdns.go b/providers/dns/pdns/pdns.go
index 751501b7..07bc663f 100644
--- a/providers/dns/pdns/pdns.go
+++ b/providers/dns/pdns/pdns.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -30,6 +31,8 @@ const (
 	EnvServerName         = envNamespace + "SERVER_NAME"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/plesk/plesk.go b/providers/dns/plesk/plesk.go
index 5b279c5f..b7a7ebf7 100644
--- a/providers/dns/plesk/plesk.go
+++ b/providers/dns/plesk/plesk.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/plesk/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	baseURL  string
diff --git a/providers/dns/porkbun/porkbun.go b/providers/dns/porkbun/porkbun.go
index 3df5120f..44bf1857 100644
--- a/providers/dns/porkbun/porkbun.go
+++ b/providers/dns/porkbun/porkbun.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/nrdcg/porkbun"
@@ -30,6 +31,8 @@ const (
 
 const minTTL = 300
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/rackspace/rackspace.go b/providers/dns/rackspace/rackspace.go
index c877de3b..b9ce8f6e 100644
--- a/providers/dns/rackspace/rackspace.go
+++ b/providers/dns/rackspace/rackspace.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/rackspace/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/rcodezero/rcodezero.go b/providers/dns/rcodezero/rcodezero.go
index 3011f193..c88caefe 100644
--- a/providers/dns/rcodezero/rcodezero.go
+++ b/providers/dns/rcodezero/rcodezero.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/rcodezero/internal"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIToken           string
diff --git a/providers/dns/regfish/regfish.go b/providers/dns/regfish/regfish.go
index 306c59bd..6a8ccee9 100644
--- a/providers/dns/regfish/regfish.go
+++ b/providers/dns/regfish/regfish.go
@@ -8,6 +8,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	regfishapi "github.com/regfish/regfish-dnsapi-go"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/regru/regru.go b/providers/dns/regru/regru.go
index 144b7faf..1501863b 100644
--- a/providers/dns/regru/regru.go
+++ b/providers/dns/regru/regru.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/regru/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username string
diff --git a/providers/dns/rfc2136/rfc2136.go b/providers/dns/rfc2136/rfc2136.go
index bd1d58a0..d533f4d1 100644
--- a/providers/dns/rfc2136/rfc2136.go
+++ b/providers/dns/rfc2136/rfc2136.go
@@ -8,6 +8,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/rfc2136/internal"
@@ -33,6 +34,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Nameserver string
diff --git a/providers/dns/rimuhosting/rimuhosting.go b/providers/dns/rimuhosting/rimuhosting.go
index 09b31d4f..9051d0ad 100644
--- a/providers/dns/rimuhosting/rimuhosting.go
+++ b/providers/dns/rimuhosting/rimuhosting.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/rimuhosting"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/route53/route53.go b/providers/dns/route53/route53.go
index 394aa506..c0a3146a 100644
--- a/providers/dns/route53/route53.go
+++ b/providers/dns/route53/route53.go
@@ -17,6 +17,7 @@ import (
 	"github.com/aws/aws-sdk-go-v2/service/route53"
 	awstypes "github.com/aws/aws-sdk-go-v2/service/route53/types"
 	"github.com/aws/aws-sdk-go-v2/service/sts"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/platform/wait"
@@ -41,6 +42,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	// Static credential chain.
diff --git a/providers/dns/safedns/safedns.go b/providers/dns/safedns/safedns.go
index cbf21702..5066db59 100644
--- a/providers/dns/safedns/safedns.go
+++ b/providers/dns/safedns/safedns.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/safedns/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AuthToken string
diff --git a/providers/dns/sakuracloud/sakuracloud.go b/providers/dns/sakuracloud/sakuracloud.go
index 0b919968..498f76c4 100644
--- a/providers/dns/sakuracloud/sakuracloud.go
+++ b/providers/dns/sakuracloud/sakuracloud.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Token              string
diff --git a/providers/dns/scaleway/scaleway.go b/providers/dns/scaleway/scaleway.go
index d3d027d9..5976e77a 100644
--- a/providers/dns/scaleway/scaleway.go
+++ b/providers/dns/scaleway/scaleway.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -16,15 +17,6 @@ import (
 	"github.com/scaleway/scaleway-sdk-go/scw"
 )
 
-const (
-	minTTL                    = 60
-	defaultPollingInterval    = 10 * time.Second
-	defaultPropagationTimeout = 120 * time.Second
-)
-
-// The access key is not used by the Scaleway client.
-const dumpAccessKey = "SCWXXXXXXXXXXXXXXXXX"
-
 // Environment variables names.
 const (
 	envNamespace = "SCALEWAY_"
@@ -42,6 +34,17 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const (
+	minTTL                    = 60
+	defaultPollingInterval    = 10 * time.Second
+	defaultPropagationTimeout = 120 * time.Second
+)
+
+// The access key is not used by the Scaleway client.
+const dumpAccessKey = "SCWXXXXXXXXXXXXXXXXX"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ProjectID          string
diff --git a/providers/dns/selectel/selectel.go b/providers/dns/selectel/selectel.go
index 933115c7..74452323 100644
--- a/providers/dns/selectel/selectel.go
+++ b/providers/dns/selectel/selectel.go
@@ -11,13 +11,12 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/selectel"
 )
 
-const minTTL = 60
-
 // Environment variables names.
 const (
 	envNamespace = "SELECTEL_"
@@ -31,6 +30,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 60
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/selectelv2/selectelv2.go b/providers/dns/selectelv2/selectelv2.go
index f5bd10c9..f638b0a3 100644
--- a/providers/dns/selectelv2/selectelv2.go
+++ b/providers/dns/selectelv2/selectelv2.go
@@ -17,16 +17,6 @@ import (
 	"golang.org/x/net/idna"
 )
 
-const tokenHeader = "X-Auth-Token"
-
-const (
-	defaultBaseURL            = "https://api.selectel.ru/domains/v2"
-	defaultTTL                = 60
-	defaultPropagationTimeout = 120 * time.Second
-	defaultPollingInterval    = 5 * time.Second
-	defaultHTTPTimeout        = 30 * time.Second
-)
-
 const (
 	envNamespace = "SELECTELV2_"
 
@@ -42,6 +32,16 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const (
+	defaultBaseURL            = "https://api.selectel.ru/domains/v2"
+	defaultTTL                = 60
+	defaultPropagationTimeout = 120 * time.Second
+	defaultPollingInterval    = 5 * time.Second
+	defaultHTTPTimeout        = 30 * time.Second
+)
+
+const tokenHeader = "X-Auth-Token"
+
 var errNotFound = errors.New("rrset not found")
 
 // Config is used to configure the creation of the DNSProvider.
diff --git a/providers/dns/selfhostde/selfhostde.go b/providers/dns/selfhostde/selfhostde.go
index 32428766..0fea9f1d 100644
--- a/providers/dns/selfhostde/selfhostde.go
+++ b/providers/dns/selfhostde/selfhostde.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/selfhostde/internal"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username string
diff --git a/providers/dns/servercow/servercow.go b/providers/dns/servercow/servercow.go
index 3db4ac45..c0c1662f 100644
--- a/providers/dns/servercow/servercow.go
+++ b/providers/dns/servercow/servercow.go
@@ -9,6 +9,7 @@ import (
 	"slices"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/servercow/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username string
diff --git a/providers/dns/shellrent/shellrent.go b/providers/dns/shellrent/shellrent.go
index d1054b37..dec1540c 100644
--- a/providers/dns/shellrent/shellrent.go
+++ b/providers/dns/shellrent/shellrent.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/shellrent/internal"
@@ -29,6 +30,8 @@ const (
 
 const defaultTTL = 3600
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 type reqKey struct {
 	domainID int
 	recordID int
diff --git a/providers/dns/simply/simply.go b/providers/dns/simply/simply.go
index 2433c4e0..d2bfb187 100644
--- a/providers/dns/simply/simply.go
+++ b/providers/dns/simply/simply.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/simply/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccountName        string
diff --git a/providers/dns/sonic/sonic.go b/providers/dns/sonic/sonic.go
index 19c5769b..80f5ea29 100644
--- a/providers/dns/sonic/sonic.go
+++ b/providers/dns/sonic/sonic.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/sonic/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	UserID             string
diff --git a/providers/dns/stackpath/stackpath.go b/providers/dns/stackpath/stackpath.go
index 97cfd8aa..8a1a2d09 100644
--- a/providers/dns/stackpath/stackpath.go
+++ b/providers/dns/stackpath/stackpath.go
@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -27,6 +28,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ClientID           string
diff --git a/providers/dns/technitium/technitium.go b/providers/dns/technitium/technitium.go
index 8ee3ccc0..b2cf2d70 100644
--- a/providers/dns/technitium/technitium.go
+++ b/providers/dns/technitium/technitium.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/technitium/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL  string
diff --git a/providers/dns/tencentcloud/tencentcloud.go b/providers/dns/tencentcloud/tencentcloud.go
index 448ca8ea..0b662f8c 100644
--- a/providers/dns/tencentcloud/tencentcloud.go
+++ b/providers/dns/tencentcloud/tencentcloud.go
@@ -7,6 +7,7 @@ import (
 	"math"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@@ -29,6 +30,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	SecretID     string
diff --git a/providers/dns/timewebcloud/timewebcloud.go b/providers/dns/timewebcloud/timewebcloud.go
index 18e4cf91..a2ab0dd6 100644
--- a/providers/dns/timewebcloud/timewebcloud.go
+++ b/providers/dns/timewebcloud/timewebcloud.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/timewebcloud/internal"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AuthToken string
diff --git a/providers/dns/transip/transip.go b/providers/dns/transip/transip.go
index a3b18d86..779704a2 100644
--- a/providers/dns/transip/transip.go
+++ b/providers/dns/transip/transip.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/transip/gotransip/v6"
@@ -24,6 +25,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccountName        string
diff --git a/providers/dns/ultradns/ultradns.go b/providers/dns/ultradns/ultradns.go
index 369af456..f95cf18e 100644
--- a/providers/dns/ultradns/ultradns.go
+++ b/providers/dns/ultradns/ultradns.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -29,6 +30,8 @@ const (
 
 const defaultEndpoint = "https://api.ultradns.com/"
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // DNSProvider implements the challenge.Provider interface.
 type DNSProvider struct {
 	config *Config
diff --git a/providers/dns/variomedia/variomedia.go b/providers/dns/variomedia/variomedia.go
index 4a7d0e90..0f2c73c0 100644
--- a/providers/dns/variomedia/variomedia.go
+++ b/providers/dns/variomedia/variomedia.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/log"
 	"github.com/go-acme/lego/v4/platform/config/env"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIToken string
diff --git a/providers/dns/vegadns/vegadns.go b/providers/dns/vegadns/vegadns.go
index 0da11ef3..b56bce97 100644
--- a/providers/dns/vegadns/vegadns.go
+++ b/providers/dns/vegadns/vegadns.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	vegaClient "github.com/OpenDNS/vegadns2client"
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 )
@@ -24,6 +25,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/vercel/vercel.go b/providers/dns/vercel/vercel.go
index 491251fe..bf3a0f53 100644
--- a/providers/dns/vercel/vercel.go
+++ b/providers/dns/vercel/vercel.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/vercel/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AuthToken          string
diff --git a/providers/dns/versio/versio.go b/providers/dns/versio/versio.go
index b1310f0b..08a2d463 100644
--- a/providers/dns/versio/versio.go
+++ b/providers/dns/versio/versio.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/versio/internal"
@@ -30,6 +31,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            *url.URL
diff --git a/providers/dns/vinyldns/vinyldns.go b/providers/dns/vinyldns/vinyldns.go
index f5f0d233..a206602d 100644
--- a/providers/dns/vinyldns/vinyldns.go
+++ b/providers/dns/vinyldns/vinyldns.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/useragent"
@@ -25,6 +26,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccessKey          string
diff --git a/providers/dns/vkcloud/vkcloud.go b/providers/dns/vkcloud/vkcloud.go
index d27feca8..e76e8713 100644
--- a/providers/dns/vkcloud/vkcloud.go
+++ b/providers/dns/vkcloud/vkcloud.go
@@ -6,19 +6,13 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/vkcloud/internal"
 	"github.com/gophercloud/gophercloud"
 )
 
-const (
-	defaultIdentityEndpoint = "https://infra.mail.ru/identity/v3/"
-	defaultDNSEndpoint      = "https://mcs.mail.ru/public-dns/v2/dns"
-)
-
-const defaultDomainName = "users"
-
 // Environment variables names.
 const (
 	envNamespace = "VK_CLOUD_"
@@ -37,6 +31,15 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+const (
+	defaultIdentityEndpoint = "https://infra.mail.ru/identity/v3/"
+	defaultDNSEndpoint      = "https://mcs.mail.ru/public-dns/v2/dns"
+)
+
+const defaultDomainName = "users"
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	ProjectID string
diff --git a/providers/dns/volcengine/volcengine.go b/providers/dns/volcengine/volcengine.go
index 7dc1054d..2fcba1b0 100644
--- a/providers/dns/volcengine/volcengine.go
+++ b/providers/dns/volcengine/volcengine.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/miekg/dns"
@@ -36,6 +37,8 @@ const (
 // https://www.volcengine.com/docs/6758/170354
 const defaultTTL = 600
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	AccessKey string
diff --git a/providers/dns/vscale/vscale.go b/providers/dns/vscale/vscale.go
index fa81f58d..a500837b 100644
--- a/providers/dns/vscale/vscale.go
+++ b/providers/dns/vscale/vscale.go
@@ -11,13 +11,12 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/selectel"
 )
 
-const minTTL = 60
-
 // Environment variables names.
 const (
 	envNamespace = "VSCALE_"
@@ -31,6 +30,10 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+const minTTL = 60
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	BaseURL            string
diff --git a/providers/dns/vultr/vultr.go b/providers/dns/vultr/vultr.go
index c6e98709..7672d205 100644
--- a/providers/dns/vultr/vultr.go
+++ b/providers/dns/vultr/vultr.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/vultr/govultr/v3"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey             string
diff --git a/providers/dns/webnames/webnames.go b/providers/dns/webnames/webnames.go
index dcc26347..78905e22 100644
--- a/providers/dns/webnames/webnames.go
+++ b/providers/dns/webnames/webnames.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/webnames/internal"
@@ -24,6 +25,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/websupport/websupport.go b/providers/dns/websupport/websupport.go
index 3a257b42..db31315d 100644
--- a/providers/dns/websupport/websupport.go
+++ b/providers/dns/websupport/websupport.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/websupport/internal"
@@ -28,6 +29,8 @@ const (
 	EnvSequenceInterval   = envNamespace + "SEQUENCE_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string
diff --git a/providers/dns/wedos/wedos.go b/providers/dns/wedos/wedos.go
index 0004c49f..85187ec4 100644
--- a/providers/dns/wedos/wedos.go
+++ b/providers/dns/wedos/wedos.go
@@ -9,6 +9,7 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/wedos/internal"
@@ -29,6 +30,8 @@ const (
 
 const minTTL = 5 * 60 // 5 minutes
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Username           string
diff --git a/providers/dns/yandex/yandex.go b/providers/dns/yandex/yandex.go
index 2886a033..c51602f6 100644
--- a/providers/dns/yandex/yandex.go
+++ b/providers/dns/yandex/yandex.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/yandex/internal"
@@ -26,6 +27,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	PddToken           string
diff --git a/providers/dns/yandex360/yandex360.go b/providers/dns/yandex360/yandex360.go
index 38aa835d..e2ee7beb 100644
--- a/providers/dns/yandex360/yandex360.go
+++ b/providers/dns/yandex360/yandex360.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/yandex360/internal"
@@ -28,6 +29,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	OAuthToken         string
diff --git a/providers/dns/yandexcloud/yandexcloud.go b/providers/dns/yandexcloud/yandexcloud.go
index 7a5d0bbe..22da1440 100644
--- a/providers/dns/yandexcloud/yandexcloud.go
+++ b/providers/dns/yandexcloud/yandexcloud.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	ycdns "github.com/yandex-cloud/go-genproto/yandex/cloud/dns/v1"
@@ -30,6 +31,8 @@ const (
 	EnvPollingInterval    = envNamespace + "POLLING_INTERVAL"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	IamToken string
diff --git a/providers/dns/zoneee/zoneee.go b/providers/dns/zoneee/zoneee.go
index 6a412a2c..7dbbc431 100644
--- a/providers/dns/zoneee/zoneee.go
+++ b/providers/dns/zoneee/zoneee.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/zoneee/internal"
@@ -27,6 +28,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	Endpoint           *url.URL
diff --git a/providers/dns/zonomi/zonomi.go b/providers/dns/zonomi/zonomi.go
index 5d1a2c79..8c7a2943 100644
--- a/providers/dns/zonomi/zonomi.go
+++ b/providers/dns/zonomi/zonomi.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/go-acme/lego/v4/challenge"
 	"github.com/go-acme/lego/v4/challenge/dns01"
 	"github.com/go-acme/lego/v4/platform/config/env"
 	"github.com/go-acme/lego/v4/providers/dns/internal/rimuhosting"
@@ -25,6 +26,8 @@ const (
 	EnvHTTPTimeout        = envNamespace + "HTTP_TIMEOUT"
 )
 
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
 // Config is used to configure the creation of the DNSProvider.
 type Config struct {
 	APIKey string


Test patch:
diff --git a/providers/dns/cloudflare/cloudflare_test.go b/providers/dns/cloudflare/cloudflare_test.go
index 0aed5125..f026bbc4 100644
--- a/providers/dns/cloudflare/cloudflare_test.go
+++ b/providers/dns/cloudflare/cloudflare_test.go
@@ -9,12 +9,18 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+const envDomain = envNamespace + "DOMAIN"
+
 var envTest = tester.NewEnvTest(
-	"CLOUDFLARE_EMAIL",
-	"CLOUDFLARE_API_KEY",
-	"CLOUDFLARE_DNS_API_TOKEN",
-	"CLOUDFLARE_ZONE_API_TOKEN").
-	WithDomain("CLOUDFLARE_DOMAIN")
+	EnvEmail,
+	EnvAPIKey,
+	EnvDNSAPIToken,
+	EnvZoneAPIToken,
+	altEnvEmail,
+	altEnvName(EnvAPIKey),
+	altEnvName(EnvDNSAPIToken),
+	altEnvName(EnvZoneAPIToken)).
+	WithDomain(envDomain)
 
 func TestNewDNSProvider(t *testing.T) {
 	testCases := []struct {
@@ -25,45 +31,45 @@ func TestNewDNSProvider(t *testing.T) {
 		{
 			desc: "success email, API key",
 			envVars: map[string]string{
-				"CLOUDFLARE_EMAIL":   "test@example.com",
-				"CLOUDFLARE_API_KEY": "123",
+				EnvEmail:  "test@example.com",
+				EnvAPIKey: "123",
 			},
 		},
 		{
 			desc: "success API token",
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN": "012345abcdef",
+				EnvDNSAPIToken: "012345abcdef",
 			},
 		},
 		{
 			desc: "success separate API tokens",
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN":  "012345abcdef",
-				"CLOUDFLARE_ZONE_API_TOKEN": "abcdef012345",
+				EnvDNSAPIToken:  "012345abcdef",
+				EnvZoneAPIToken: "abcdef012345",
 			},
 		},
 		{
 			desc: "missing credentials",
 			envVars: map[string]string{
-				"CLOUDFLARE_EMAIL":         "",
-				"CLOUDFLARE_API_KEY":       "",
-				"CLOUDFLARE_DNS_API_TOKEN": "",
+				EnvEmail:       "",
+				EnvAPIKey:      "",
+				EnvDNSAPIToken: "",
 			},
 			expected: "cloudflare: some credentials information are missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY or some credentials information are missing: CLOUDFLARE_DNS_API_TOKEN,CLOUDFLARE_ZONE_API_TOKEN",
 		},
 		{
 			desc: "missing email",
 			envVars: map[string]string{
-				"CLOUDFLARE_EMAIL":   "",
-				"CLOUDFLARE_API_KEY": "key",
+				EnvEmail:  "",
+				EnvAPIKey: "key",
 			},
 			expected: "cloudflare: some credentials information are missing: CLOUDFLARE_EMAIL or some credentials information are missing: CLOUDFLARE_DNS_API_TOKEN,CLOUDFLARE_ZONE_API_TOKEN",
 		},
 		{
 			desc: "missing api key",
 			envVars: map[string]string{
-				"CLOUDFLARE_EMAIL":   "awesome@possum.com",
-				"CLOUDFLARE_API_KEY": "",
+				EnvEmail:  "awesome@possum.com",
+				EnvAPIKey: "",
 			},
 			expected: "cloudflare: some credentials information are missing: CLOUDFLARE_API_KEY or some credentials information are missing: CLOUDFLARE_DNS_API_TOKEN,CLOUDFLARE_ZONE_API_TOKEN",
 		},
@@ -110,7 +116,7 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 		{
 			desc: "same client when zone token is missing",
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN": "123",
+				EnvDNSAPIToken: "123",
 			},
 			expected: expected{
 				dnsToken:   "123",
@@ -121,8 +127,8 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 		{
 			desc: "same client when zone token equals dns token",
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN":  "123",
-				"CLOUDFLARE_ZONE_API_TOKEN": "123",
+				EnvDNSAPIToken:  "123",
+				EnvZoneAPIToken: "123",
 			},
 			expected: expected{
 				dnsToken:   "123",
@@ -133,7 +139,7 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 		{
 			desc: "failure when only zone api given",
 			envVars: map[string]string{
-				"CLOUDFLARE_ZONE_API_TOKEN": "123",
+				EnvZoneAPIToken: "123",
 			},
 			expected: expected{
 				error: "cloudflare: some credentials information are missing: CLOUDFLARE_EMAIL,CLOUDFLARE_API_KEY or some credentials information are missing: CLOUDFLARE_DNS_API_TOKEN",
@@ -142,8 +148,8 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 		{
 			desc: "different clients when zone and dns token differ",
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN":  "123",
-				"CLOUDFLARE_ZONE_API_TOKEN": "abc",
+				EnvDNSAPIToken:  "123",
+				EnvZoneAPIToken: "abc",
 			},
 			expected: expected{
 				dnsToken:   "123",
@@ -154,10 +160,10 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 		{
 			desc: "aliases work as expected", // CLOUDFLARE_* takes precedence over CF_*
 			envVars: map[string]string{
-				"CLOUDFLARE_DNS_API_TOKEN":  "123",
-				"CF_DNS_API_TOKEN":          "456",
-				"CLOUDFLARE_ZONE_API_TOKEN": "abc",
-				"CF_ZONE_API_TOKEN":         "def",
+				EnvDNSAPIToken:              "123",
+				altEnvName(EnvDNSAPIToken):  "456",
+				EnvZoneAPIToken:             "abc",
+				altEnvName(EnvZoneAPIToken): "def",
 			},
 			expected: expected{
 				dnsToken:   "123",
@@ -169,9 +175,9 @@ func TestNewDNSProviderWithToken(t *testing.T) {
 
 	defer envTest.RestoreEnv()
 	localEnvTest := tester.NewEnvTest(
-		"CLOUDFLARE_DNS_API_TOKEN", "CF_DNS_API_TOKEN",
-		"CLOUDFLARE_ZONE_API_TOKEN", "CF_ZONE_API_TOKEN",
-	).WithDomain("CLOUDFLARE_DOMAIN")
+		EnvDNSAPIToken, altEnvName(EnvDNSAPIToken),
+		EnvZoneAPIToken, altEnvName(EnvZoneAPIToken),
+	).WithDomain(envDomain)
 	envTest.ClearEnv()
 
 	for _, test := range testCases {
diff --git a/providers/dns/namecheap/namecheap_test.go b/providers/dns/namecheap/namecheap_test.go
index 4f4036de..01f87aaf 100644
--- a/providers/dns/namecheap/namecheap_test.go
+++ b/providers/dns/namecheap/namecheap_test.go
@@ -127,7 +127,7 @@ func mockDNSProvider(t *testing.T, baseURL string) *DNSProvider {
 func assertHdr(t *testing.T, tc *testCase, values *url.Values) {
 	t.Helper()
 
-	ch, _ := newChallenge(tc.domain, "")
+	ch, _ := newPseudoRecord(tc.domain, "")
 	assert.Equal(t, envTestUser, values.Get("ApiUser"), "ApiUser")
 	assert.Equal(t, envTestKey, values.Get("ApiKey"), "ApiKey")
 	assert.Equal(t, envTestUser, values.Get("UserName"), "UserName")
@@ -177,7 +177,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
 	}
 }
 
-func TestDomainSplit(t *testing.T) {
+func Test_newPseudoRecord_domainSplit(t *testing.T) {
 	tests := []struct {
 		domain string
 		valid  bool
@@ -205,7 +205,7 @@ func TestDomainSplit(t *testing.T) {
 	for _, test := range tests {
 		t.Run(test.domain, func(t *testing.T) {
 			valid := true
-			ch, err := newChallenge(test.domain, "")
+			ch, err := newPseudoRecord(test.domain, "")
 			if err != nil {
 				valid = false
 			}