Repository: envoyproxy/gateway
Pull request #3416 (2024-05-17 06:38:54)

doc: update api doc
fix: https://github.com/envoyproxy/gateway/issues/3414

zirain: > LGTM! Shall we wait [this PR](https://github.com/elastic/crd-ref-docs/pull/82) to be merged?

we can do that with a following PR.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/3416?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 67.25%. Comparing base [(`99f9132`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/99f9132690c963391baed9ad70f5e1df91d7c3d9?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`9a107be`)](https://app.codecov.io/gh/envoyproxy/gateway/pull/3416?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #3416      +/-   ##
==========================================
+ Coverage   67.23%   67.25%   +0.02%     
==========================================
  Files         166      166              
  Lines       19439    19439              
==========================================
+ Hits        13070    13074       +4     
+ Misses       5424     5421       -3     
+ Partials      945      944       -1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/3416?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


Patch:
diff --git a/api/v1alpha1/envoygateway_metrics_types.go b/api/v1alpha1/envoygateway_metrics_types.go
index 0b827a06a..7d796e848 100644
--- a/api/v1alpha1/envoygateway_metrics_types.go
+++ b/api/v1alpha1/envoygateway_metrics_types.go
@@ -5,6 +5,8 @@
 
 package v1alpha1
 
+import gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
+
 // EnvoyGatewayMetrics defines control plane push/pull metrics configurations.
 type EnvoyGatewayMetrics struct {
 	// Sinks defines the metric sinks where metrics are sent to.
@@ -38,6 +40,18 @@ type EnvoyGatewayOpenTelemetrySink struct {
 	// +kubebuilder:validation:Minimum=0
 	// +kubebuilder:default=4317
 	Port int32 `json:"port,omitempty"`
+	// ExportInterval configures the intervening time between exports for a
+	// Sink. This option overrides any value set for the
+	// OTEL_METRIC_EXPORT_INTERVAL environment variable.
+	// If ExportInterval is less than or equal to zero, 60 seconds
+	// is used as the default.
+	ExportInterval *gatewayv1.Duration `json:"exportInterval,omitempty"`
+	// ExportTimeout configures the time a Sink waits for an export to
+	// complete before canceling it. This option overrides any value set for the
+	// OTEL_METRIC_EXPORT_TIMEOUT environment variable.
+	// If ExportTimeout is less than or equal to zero, 30 seconds
+	// is used as the default.
+	ExportTimeout *gatewayv1.Duration `json:"exportTimeout,omitempty"`
 }
 
 // EnvoyGatewayPrometheusProvider will expose prometheus endpoint in pull mode.
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index e2d32b0df..c3163b73a 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -1332,7 +1332,7 @@ func (in *EnvoyGatewayMetricSink) DeepCopyInto(out *EnvoyGatewayMetricSink) {
 	if in.OpenTelemetry != nil {
 		in, out := &in.OpenTelemetry, &out.OpenTelemetry
 		*out = new(EnvoyGatewayOpenTelemetrySink)
-		**out = **in
+		(*in).DeepCopyInto(*out)
 	}
 }
 
@@ -1376,6 +1376,16 @@ func (in *EnvoyGatewayMetrics) DeepCopy() *EnvoyGatewayMetrics {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *EnvoyGatewayOpenTelemetrySink) DeepCopyInto(out *EnvoyGatewayOpenTelemetrySink) {
 	*out = *in
+	if in.ExportInterval != nil {
+		in, out := &in.ExportInterval, &out.ExportInterval
+		*out = new(apisv1.Duration)
+		**out = **in
+	}
+	if in.ExportTimeout != nil {
+		in, out := &in.ExportTimeout, &out.ExportTimeout
+		*out = new(apisv1.Duration)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyGatewayOpenTelemetrySink.
diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go
index cde6d26a1..f51b01122 100644
--- a/internal/gatewayapi/backendtlspolicy.go
+++ b/internal/gatewayapi/backendtlspolicy.go
@@ -8,7 +8,6 @@ package gatewayapi
 import (
 	"fmt"
 
-	corev1 "k8s.io/api/core/v1"
 	"k8s.io/utils/ptr"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
@@ -29,7 +28,7 @@ func (t *Translator) processBackendTLSPolicy(
 		return nil
 	}
 
-	tlsBundle, err := getBackendTLSBundle(policy, resources.ConfigMaps)
+	tlsBundle, err := getBackendTLSBundle(policy, resources)
 	if err == nil && tlsBundle == nil {
 		return nil
 	}
@@ -104,7 +103,7 @@ func getBackendTLSPolicy(policies []*gwapiv1a3.BackendTLSPolicy, backendRef gwap
 	return nil
 }
 
-func getBackendTLSBundle(backendTLSPolicy *gwapiv1a3.BackendTLSPolicy, configmaps []*corev1.ConfigMap) (*ir.TLSUpstreamConfig, error) {
+func getBackendTLSBundle(backendTLSPolicy *gwapiv1a3.BackendTLSPolicy, resources *Resources) (*ir.TLSUpstreamConfig, error) {
 	tlsBundle := &ir.TLSUpstreamConfig{
 		SNI:                 string(backendTLSPolicy.Spec.Validation.Hostname),
 		UseSystemTrustStore: ptr.Deref(backendTLSPolicy.Spec.Validation.WellKnownCACertificates, "") == gwapiv1a3.WellKnownCACertificatesSystem,
@@ -113,23 +112,36 @@ func getBackendTLSBundle(backendTLSPolicy *gwapiv1a3.BackendTLSPolicy, configmap
 		return tlsBundle, nil
 	}
 
-	caRefMap := make(map[string]string)
-
-	for _, caRef := range backendTLSPolicy.Spec.Validation.CACertificateRefs {
-		caRefMap[string(caRef.Name)] = string(caRef.Kind)
-	}
-
 	ca := ""
-
-	for _, cmap := range configmaps {
-		if kind, ok := caRefMap[cmap.Name]; ok && kind == cmap.Kind {
-			if crt, dataOk := cmap.Data["ca.crt"]; dataOk {
-				if ca != "" {
-					ca += "\n"
+	for _, caRef := range backendTLSPolicy.Spec.Validation.CACertificateRefs {
+		kind := string(caRef.Kind)
+
+		switch kind {
+		case KindConfigMap:
+			for _, cmap := range resources.ConfigMaps {
+				if cmap.Name == string(caRef.Name) {
+					if crt, dataOk := cmap.Data["ca.crt"]; dataOk {
+						if ca != "" {
+							ca += "\n"
+						}
+						ca += crt
+					} else {
+						return nil, fmt.Errorf("no ca found in configmap %s", cmap.Name)
+					}
+				}
+			}
+		case KindSecret:
+			for _, secret := range resources.Secrets {
+				if secret.Name == string(caRef.Name) {
+					if crt, dataOk := secret.Data["ca.crt"]; dataOk {
+						if ca != "" {
+							ca += "\n"
+						}
+						ca += string(crt)
+					} else {
+						return nil, fmt.Errorf("no ca found in secret %s", secret.Name)
+					}
 				}
-				ca += crt
-			} else {
-				return nil, fmt.Errorf("no ca found in configmap %s", cmap.Name)
 			}
 		}
 	}
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index d29f7d106..1664370d5 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -6,6 +6,7 @@
 package gatewayapi
 
 import (
+	"errors"
 	"fmt"
 	"math"
 	"net"
@@ -13,7 +14,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/pkg/errors"
+	perr "github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -286,22 +287,23 @@ func resolveBTPolicyRouteTargetRef(policy *egv1a1.BackendTrafficPolicy, routes m
 
 func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.BackendTrafficPolicy, route RouteContext, xdsIR XdsIRMap) error {
 	var (
-		rl  *ir.RateLimit
-		lb  *ir.LoadBalancer
-		pp  *ir.ProxyProtocol
-		hc  *ir.HealthCheck
-		cb  *ir.CircuitBreaker
-		fi  *ir.FaultInjection
-		to  *ir.Timeout
-		ka  *ir.TCPKeepalive
-		rt  *ir.Retry
-		err error
+		rl        *ir.RateLimit
+		lb        *ir.LoadBalancer
+		pp        *ir.ProxyProtocol
+		hc        *ir.HealthCheck
+		cb        *ir.CircuitBreaker
+		fi        *ir.FaultInjection
+		to        *ir.Timeout
+		ka        *ir.TCPKeepalive
+		rt        *ir.Retry
+		err, errs error
 	)
 
 	// Build IR
 	if policy.Spec.RateLimit != nil {
 		if rl, err = t.buildRateLimit(policy); err != nil {
-			return errors.Wrap(err, "RateLimit")
+			err = perr.WithMessage(err, "RateLimit")
+			errs = errors.Join(errs, err)
 		}
 	}
 	if policy.Spec.LoadBalancer != nil {
@@ -315,30 +317,37 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 	}
 	if policy.Spec.CircuitBreaker != nil {
 		if cb, err = t.buildCircuitBreaker(policy); err != nil {
-			return errors.Wrap(err, "CircuitBreaker")
+			err = perr.WithMessage(err, "CircuitBreaker")
+			errs = errors.Join(errs, err)
 		}
 	}
-
 	if policy.Spec.FaultInjection != nil {
 		fi = t.buildFaultInjection(policy)
 	}
 	if policy.Spec.TCPKeepalive != nil {
 		if ka, err = t.buildTCPKeepAlive(policy); err != nil {
-			return errors.Wrap(err, "TCPKeepalive")
+			err = perr.WithMessage(err, "TCPKeepalive")
+			errs = errors.Join(errs, err)
 		}
 	}
 	if policy.Spec.Retry != nil {
 		rt = t.buildRetry(policy)
 	}
-	// Apply IR to all relevant routes
-	prefix := irRoutePrefix(route)
-
 	if policy.Spec.Timeout != nil {
 		if to, err = t.buildTimeout(policy, nil); err != nil {
-			return errors.Wrap(err, "Timeout")
+			err = perr.WithMessage(err, "Timeout")
+			errs = errors.Join(errs, err)
 		}
 	}
 
+	// Early return if got any errors
+	if errs != nil {
+		return errs
+	}
+
+	// Apply IR to all relevant routes
+	prefix := irRoutePrefix(route)
+
 	for _, x := range xdsIR {
 		for _, tcp := range x.TCP {
 			for _, r := range tcp.Routes {
@@ -384,10 +393,9 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 
 					// Some timeout setting originate from the route.
 					if policy.Spec.Timeout != nil {
-						if to, err = t.buildTimeout(policy, r); err != nil {
-							return errors.Wrap(err, "Timeout")
+						if to, err = t.buildTimeout(policy, r); err == nil {
+							r.Traffic.Timeout = to
 						}
-						r.Traffic.Timeout = to
 					}
 
 					if policy.Spec.UseClientProtocol != nil {
@@ -403,22 +411,23 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 
 func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.BackendTrafficPolicy, gateway *GatewayContext, xdsIR XdsIRMap) error {
 	var (
-		rl  *ir.RateLimit
-		lb  *ir.LoadBalancer
-		pp  *ir.ProxyProtocol
-		hc  *ir.HealthCheck
-		cb  *ir.CircuitBreaker
-		fi  *ir.FaultInjection
-		ct  *ir.Timeout
-		ka  *ir.TCPKeepalive
-		rt  *ir.Retry
-		err error
+		rl        *ir.RateLimit
+		lb        *ir.LoadBalancer
+		pp        *ir.ProxyProtocol
+		hc        *ir.HealthCheck
+		cb        *ir.CircuitBreaker
+		fi        *ir.FaultInjection
+		ct        *ir.Timeout
+		ka        *ir.TCPKeepalive
+		rt        *ir.Retry
+		err, errs error
 	)
 
 	// Build IR
 	if policy.Spec.RateLimit != nil {
 		if rl, err = t.buildRateLimit(policy); err != nil {
-			return errors.Wrap(err, "RateLimit")
+			err = perr.WithMessage(err, "RateLimit")
+			errs = errors.Join(errs, err)
 		}
 	}
 	if policy.Spec.LoadBalancer != nil {
@@ -432,7 +441,8 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 	}
 	if policy.Spec.CircuitBreaker != nil {
 		if cb, err = t.buildCircuitBreaker(policy); err != nil {
-			return errors.Wrap(err, "CircuitBreaker")
+			err = perr.WithMessage(err, "CircuitBreaker")
+			errs = errors.Join(errs, err)
 		}
 	}
 	if policy.Spec.FaultInjection != nil {
@@ -440,12 +450,24 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 	}
 	if policy.Spec.TCPKeepalive != nil {
 		if ka, err = t.buildTCPKeepAlive(policy); err != nil {
-			return errors.Wrap(err, "TCPKeepalive")
+			err = perr.WithMessage(err, "TCPKeepalive")
+			errs = errors.Join(errs, err)
 		}
 	}
 	if policy.Spec.Retry != nil {
 		rt = t.buildRetry(policy)
 	}
+	if policy.Spec.Timeout != nil {
+		if ct, err = t.buildTimeout(policy, nil); err != nil {
+			err = perr.WithMessage(err, "Timeout")
+			errs = errors.Join(errs, err)
+		}
+	}
+
+	// Early return if got any errors
+	if errs != nil {
+		return errs
+	}
 
 	// Apply IR to all the routes within the specific Gateway
 	// If the feature is already set, then skip it, since it must be have
@@ -456,12 +478,6 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 
 	policyTarget := irStringKey(policy.Namespace, string(policy.Spec.TargetRef.Name))
 
-	if policy.Spec.Timeout != nil {
-		if ct, err = t.buildTimeout(policy, nil); err != nil {
-			return errors.Wrap(err, "Timeout")
-		}
-	}
-
 	for _, tcp := range x.TCP {
 		gatewayName := tcp.Name[0:strings.LastIndex(tcp.Name, "/")]
 		if t.MergeGateways && gatewayName != policyTarget {
@@ -541,10 +557,9 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 			r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname)
 
 			if policy.Spec.Timeout != nil {
-				if ct, err = t.buildTimeout(policy, r); err != nil {
-					return errors.Wrap(err, "Timeout")
+				if ct, err = t.buildTimeout(policy, r); err == nil {
+					r.Traffic.Timeout = ct
 				}
-				r.Traffic.Timeout = ct
 			}
 
 			if policy.Spec.UseClientProtocol != nil {
@@ -1009,8 +1024,10 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) (*
 
 func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTTPRoute) (*ir.Timeout, error) {
 	var (
-		tto *ir.TCPTimeout
-		hto *ir.HTTPTimeout
+		tto  *ir.TCPTimeout
+		hto  *ir.HTTPTimeout
+		terr bool
+		errs error
 	)
 
 	pto := policy.Spec.Timeout
@@ -1018,11 +1035,12 @@ func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTT
 	if pto.TCP != nil && pto.TCP.ConnectTimeout != nil {
 		d, err := time.ParseDuration(string(*pto.TCP.ConnectTimeout))
 		if err != nil {
-			return nil, fmt.Errorf("invalid ConnectTimeout value %s", *pto.TCP.ConnectTimeout)
-		}
-
-		tto = &ir.TCPTimeout{
-			ConnectTimeout: ptr.To(metav1.Duration{Duration: d}),
+			terr = true
+			errs = errors.Join(errs, fmt.Errorf("invalid ConnectTimeout value %s", *pto.TCP.ConnectTimeout))
+		} else {
+			tto = &ir.TCPTimeout{
+				ConnectTimeout: ptr.To(metav1.Duration{Duration: d}),
+			}
 		}
 	}
 
@@ -1033,19 +1051,21 @@ func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTT
 		if pto.HTTP.ConnectionIdleTimeout != nil {
 			d, err := time.ParseDuration(string(*pto.HTTP.ConnectionIdleTimeout))
 			if err != nil {
-				return nil, fmt.Errorf("invalid ConnectionIdleTimeout value %s", *pto.HTTP.ConnectionIdleTimeout)
+				terr = true
+				errs = errors.Join(errs, fmt.Errorf("invalid ConnectionIdleTimeout value %s", *pto.HTTP.ConnectionIdleTimeout))
+			} else {
+				cit = ptr.To(metav1.Duration{Duration: d})
 			}
-
-			cit = ptr.To(metav1.Duration{Duration: d})
 		}
 
 		if pto.HTTP.MaxConnectionDuration != nil {
 			d, err := time.ParseDuration(string(*pto.HTTP.MaxConnectionDuration))
 			if err != nil {
-				return nil, fmt.Errorf("invalid MaxConnectionDuration value %s", *pto.HTTP.MaxConnectionDuration)
+				terr = true
+				errs = errors.Join(errs, fmt.Errorf("invalid MaxConnectionDuration value %s", *pto.HTTP.MaxConnectionDuration))
+			} else {
+				mcd = ptr.To(metav1.Duration{Duration: d})
 			}
-
-			mcd = ptr.To(metav1.Duration{Duration: d})
 		}
 
 		hto = &ir.HTTPTimeout{
@@ -1056,28 +1076,36 @@ func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTT
 
 	// http request timeout is translated during the gateway-api route resource translation
 	// merge route timeout setting with backendtrafficpolicy timeout settings
-	if r != nil &&
-		r.Traffic != nil &&
-		r.Traffic.Timeout != nil &&
-		r.Traffic.Timeout.HTTP != nil &&
-		r.Traffic.Timeout.HTTP.RequestTimeout != nil {
-		if hto == nil {
-			hto = &ir.HTTPTimeout{
-				RequestTimeout: r.Traffic.Timeout.HTTP.RequestTimeout,
+	if terr {
+		if r != nil && r.Traffic != nil && r.Traffic.Timeout != nil {
+			return r.Traffic.Timeout.DeepCopy(), errs
+		}
+	} else {
+		// http request timeout is translated during the gateway-api route resource translation
+		// merge route timeout setting with backendtrafficpolicy timeout settings
+		if r != nil &&
+			r.Traffic != nil &&
+			r.Traffic.Timeout != nil &&
+			r.Traffic.Timeout.HTTP != nil &&
+			r.Traffic.Timeout.HTTP.RequestTimeout != nil {
+			if hto == nil {
+				hto = &ir.HTTPTimeout{
+					RequestTimeout: r.Traffic.Timeout.HTTP.RequestTimeout,
+				}
+			} else {
+				hto.RequestTimeout = r.Traffic.Timeout.HTTP.RequestTimeout
 			}
-		} else {
-			hto.RequestTimeout = r.Traffic.Timeout.HTTP.RequestTimeout
 		}
-	}
 
-	if hto != nil || tto != nil {
-		return &ir.Timeout{
-			TCP:  tto,
-			HTTP: hto,
-		}, nil
+		if hto != nil || tto != nil {
+			return &ir.Timeout{
+				TCP:  tto,
+				HTTP: hto,
+			}, nil
+		}
 	}
 
-	return nil, nil
+	return nil, errs
 }
 
 func int64ToUint32(in int64) (uint32, bool) {
diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go
index 1cf802cb2..c5da32c4c 100644
--- a/internal/gatewayapi/clienttrafficpolicy.go
+++ b/internal/gatewayapi/clienttrafficpolicy.go
@@ -13,6 +13,7 @@ import (
 	"strings"
 	"time"
 
+	perr "github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -385,22 +386,24 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie
 	var (
 		keepalive           *ir.TCPKeepalive
 		connection          *ir.Connection
-		enableProxyProtocol bool
 		tlsConfig           *ir.TLSConfig
-		err                 error
+		enableProxyProtocol bool
+		err, errs           error
 	)
 
 	// Build common IR shared by HTTP and TCP listeners, return early if some field is invalid.
 	// Translate TCPKeepalive
 	keepalive, err = buildKeepAlive(policy.Spec.TCPKeepalive)
 	if err != nil {
-		return err
+		err = perr.WithMessage(err, "TCP KeepAlive")
+		errs = errors.Join(errs, err)
 	}
 
 	// Translate Connection
 	connection, err = buildConnection(policy.Spec.Connection)
 	if err != nil {
-		return err
+		err = perr.WithMessage(err, "Connection")
+		errs = errors.Join(errs, err)
 	}
 
 	// Translate Proxy Protocol
@@ -418,18 +421,21 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie
 		translatePathSettings(policy.Spec.Path, httpIR)
 
 		// Translate Client Timeout Settings
-		if err := translateClientTimeout(policy.Spec.Timeout, httpIR); err != nil {
-			return err
+		if err = translateClientTimeout(policy.Spec.Timeout, httpIR); err != nil {
+			err = perr.WithMessage(err, "Timeout")
+			errs = errors.Join(errs, err)
 		}
 
 		// Translate HTTP1 Settings
-		if err := translateHTTP1Settings(policy.Spec.HTTP1, httpIR); err != nil {
-			return err
+		if err = translateHTTP1Settings(policy.Spec.HTTP1, httpIR); err != nil {
+			err = perr.WithMessage(err, "HTTP1")
+			errs = errors.Join(errs, err)
 		}
 
 		// Translate HTTP2 Settings
-		if err := translateHTTP2Settings(policy.Spec.HTTP2, httpIR); err != nil {
-			return err
+		if err = translateHTTP2Settings(policy.Spec.HTTP2, httpIR); err != nil {
+			err = perr.WithMessage(err, "HTTP2")
+			errs = errors.Join(errs, err)
 		}
 
 		// enable http3 if set and TLS is enabled
@@ -453,7 +459,13 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie
 		// Translate TLS parameters
 		tlsConfig, err = t.buildListenerTLSParameters(policy, httpIR.TLS, resources)
 		if err != nil {
-			return err
+			err = perr.WithMessage(err, "TLS")
+			errs = errors.Join(errs, err)
+		}
+
+		// Early return if got any errors
+		if errs != nil {
+			return errs
 		}
 
 		httpIR.TCPKeepalive = keepalive
@@ -466,7 +478,13 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie
 		// Translate TLS parameters
 		tlsConfig, err = t.buildListenerTLSParameters(policy, tcpIR.TLS, resources)
 		if err != nil {
-			return err
+			err = perr.WithMessage(err, "TLS")
+			errs = errors.Join(errs, err)
+		}
+
+		// Early return if got any errors
+		if errs != nil {
+			return errs
 		}
 
 		tcpIR.TCPKeepalive = keepalive
@@ -616,7 +634,7 @@ func translateHTTP1Settings(http1Settings *egv1a1.HTTP1Settings, httpIR *ir.HTTP
 				}
 			}
 			if defaultHost == nil {
-				return fmt.Errorf("can't set http10 default host on listener with only wildcard hostnames")
+				return fmt.Errorf("cannot set http10 default host on listener with only wildcard hostnames")
 			}
 		}
 		// If useDefaultHost was set, then defaultHost will have the hostname to use.
diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go
index 905919ea8..16229f2d7 100644
--- a/internal/gatewayapi/envoyextensionpolicy.go
+++ b/internal/gatewayapi/envoyextensionpolicy.go
@@ -12,6 +12,7 @@ import (
 	"strings"
 	"time"
 
+	perr "github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -293,16 +294,23 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute(policy *egv1a1.EnvoyE
 	)
 
 	if extProcs, err = t.buildExtProcs(policy, resources); err != nil {
+		err = perr.WithMessage(err, "ExtProcs")
 		errs = errors.Join(errs, err)
 	}
 	if wasms, err = t.buildWasms(policy); err != nil {
+		err = perr.WithMessage(err, "WASMs")
 		errs = errors.Join(errs, err)
 	}
 
+	// Early return if got any errors
+	if errs != nil {
+		return errs
+	}
+
 	// Apply IR to all relevant routes
 	prefix := irRoutePrefix(route)
-	for _, ir := range xdsIR {
-		for _, http := range ir.HTTP {
+	for _, x := range xdsIR {
+		for _, http := range x.HTTP {
 			for _, r := range http.Routes {
 				// Apply if there is a match
 				if strings.HasPrefix(r.Name, prefix) {
@@ -313,25 +321,7 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute(policy *egv1a1.EnvoyE
 		}
 	}
 
-	return errs
-}
-
-func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resources *Resources) ([]ir.ExtProc, error) {
-	var extProcIRList []ir.ExtProc
-
-	if policy == nil {
-		return nil, nil
-	}
-
-	for idx, ep := range policy.Spec.ExtProc {
-		name := irConfigNameForEEP(policy, idx)
-		extProcIR, err := t.buildExtProc(name, utils.NamespacedName(policy), ep, idx, resources)
-		if err != nil {
-			return nil, err
-		}
-		extProcIRList = append(extProcIRList, *extProcIR)
-	}
-	return extProcIRList, nil
+	return nil
 }
 
 func (t *Translator) translateEnvoyExtensionPolicyForGateway(policy *egv1a1.EnvoyExtensionPolicy,
@@ -343,20 +333,27 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(policy *egv1a1.Envo
 		err, errs error
 	)
 
-	irKey := t.getIRKey(gateway.Gateway)
-	// Should exist since we've validated this
-	ir := xdsIR[irKey]
-
-	policyTarget := irStringKey(policy.Namespace, string(policy.Spec.TargetRef.Name))
-
 	if extProcs, err = t.buildExtProcs(policy, resources); err != nil {
+		err = perr.WithMessage(err, "ExtProcs")
 		errs = errors.Join(errs, err)
 	}
 	if wasms, err = t.buildWasms(policy); err != nil {
+		err = perr.WithMessage(err, "WASMs")
 		errs = errors.Join(errs, err)
 	}
 
-	for _, http := range ir.HTTP {
+	// Early return if got any errors
+	if errs != nil {
+		return errs
+	}
+
+	irKey := t.getIRKey(gateway.Gateway)
+	// Should exist since we've validated this
+	x := xdsIR[irKey]
+
+	policyTarget := irStringKey(policy.Namespace, string(policy.Spec.TargetRef.Name))
+
+	for _, http := range x.HTTP {
 		gatewayName := http.Name[0:strings.LastIndex(http.Name, "/")]
 		if t.MergeGateways && gatewayName != policyTarget {
 			continue
@@ -380,7 +377,25 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(policy *egv1a1.Envo
 		}
 	}
 
-	return errs
+	return nil
+}
+
+func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resources *Resources) ([]ir.ExtProc, error) {
+	var extProcIRList []ir.ExtProc
+
+	if policy == nil {
+		return nil, nil
+	}
+
+	for idx, ep := range policy.Spec.ExtProc {
+		name := irConfigNameForEEP(policy, idx)
+		extProcIR, err := t.buildExtProc(name, utils.NamespacedName(policy), ep, idx, resources)
+		if err != nil {
+			return nil, err
+		}
+		extProcIRList = append(extProcIRList, *extProcIR)
+	}
+	return extProcIRList, nil
 }
 
 func (t *Translator) buildExtProc(
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index e68cf3fab..bfb4d9e7e 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -16,6 +16,7 @@ import (
 	"strconv"
 	"strings"
 
+	perr "github.com/pkg/errors"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
@@ -351,6 +352,7 @@ func (t *Translator) translateSecurityPolicyForRoute(
 		if oidc, err = t.buildOIDC(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "OIDC")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -359,6 +361,7 @@ func (t *Translator) translateSecurityPolicyForRoute(
 		if basicAuth, err = t.buildBasicAuth(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "BasicAuth")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -367,6 +370,7 @@ func (t *Translator) translateSecurityPolicyForRoute(
 		if extAuth, err = t.buildExtAuth(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "ExtAuth")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -423,6 +427,7 @@ func (t *Translator) translateSecurityPolicyForGateway(
 		if oidc, err = t.buildOIDC(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "OIDC")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -431,6 +436,7 @@ func (t *Translator) translateSecurityPolicyForGateway(
 		if basicAuth, err = t.buildBasicAuth(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "BasicAuth")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -439,6 +445,7 @@ func (t *Translator) translateSecurityPolicyForGateway(
 		if extAuth, err = t.buildExtAuth(
 			policy,
 			resources); err != nil {
+			err = perr.WithMessage(err, "ExtAuth")
 			errs = errors.Join(errs, err)
 		}
 	}
@@ -585,7 +592,7 @@ func (t *Translator) buildOIDC(
 	// Generate a unique cookie suffix for oauth filters
 	suffix := utils.Digest32(string(policy.UID))
 
-	// Get the HMAC secret
+	// Get the HMAC secret.
 	// HMAC secret is generated by the CertGen job and stored in a secret
 	// We need to rotate the HMAC secret in the future, probably the same
 	// way we rotate the certs generated by the CertGen job.
diff --git a/internal/gatewayapi/status/conditions.go b/internal/gatewayapi/status/conditions.go
index f2e735307..2b710189a 100644
--- a/internal/gatewayapi/status/conditions.go
+++ b/internal/gatewayapi/status/conditions.go
@@ -67,7 +67,7 @@ func conditionChanged(a, b metav1.Condition) bool {
 
 // Error2ConditionMsg format the error string to a Status condition message.
 // * Convert the first letter to capital
-// * Append "." to the string if it doesn't exit
+// * Append "." to the string if it doesn't exist
 func Error2ConditionMsg(err error) string {
 	if err == nil {
 		return ""
@@ -86,6 +86,12 @@ func Error2ConditionMsg(err error) string {
 		runes[0] = unicode.ToUpper(runes[0])
 	}
 
+	// Check if the last rune is a punctuation '.' and append it if not
+	last := runes[len(runes)-1]
+	if !unicode.IsPunct(last) || last != '.' {
+		runes = append(runes, '.')
+	}
+
 	// Convert the rune slice back to a string
 	return string(runes)
 }
diff --git a/internal/metrics/register.go b/internal/metrics/register.go
index e6332aeb8..a73d43371 100644
--- a/internal/metrics/register.go
+++ b/internal/metrics/register.go
@@ -31,7 +31,11 @@ const (
 
 // Init initializes and registers the global metrics server.
 func Init(cfg *config.Server) error {
-	options := newOptions(cfg)
+	options, err := newOptions(cfg)
+	if err != nil {
+		return err
+	}
+
 	handler, err := registerForHandler(options)
 	if err != nil {
 		return err
@@ -71,7 +75,7 @@ func start(address string, handler http.Handler) error {
 	return nil
 }
 
-func newOptions(svr *config.Server) registerOptions {
+func newOptions(svr *config.Server) (registerOptions, error) {
 	newOpts := registerOptions{}
 	newOpts.address = net.JoinHostPort(v1alpha1.GatewayMetricsHost, fmt.Sprint(v1alpha1.GatewayMetricsPort))
 
@@ -84,14 +88,37 @@ func newOptions(svr *config.Server) registerOptions {
 	}
 
 	for _, config := range svr.EnvoyGateway.GetEnvoyGatewayTelemetry().Metrics.Sinks {
-		newOpts.pushOptions.sinks = append(newOpts.pushOptions.sinks, metricsSink{
+		sink := metricsSink{
 			host:     config.OpenTelemetry.Host,
 			port:     config.OpenTelemetry.Port,
 			protocol: config.OpenTelemetry.Protocol,
-		})
+		}
+
+		// we do not explicitly set default values for ExporterInterval and ExporterTimeout
+		// instead, let the upstream repository set default values for it
+		if config.OpenTelemetry.ExportInterval != nil && len(*config.OpenTelemetry.ExportInterval) != 0 {
+			interval, err := time.ParseDuration(string(*config.OpenTelemetry.ExportInterval))
+			if err != nil {
+				metricsLogger.Error(err, "failed to parse exporter interval time format")
+				return newOpts, err
+			}
+
+			sink.exportInterval = interval
+		}
+		if config.OpenTelemetry.ExportTimeout != nil && len(*config.OpenTelemetry.ExportTimeout) != 0 {
+			timeout, err := time.ParseDuration(string(*config.OpenTelemetry.ExportTimeout))
+			if err != nil {
+				metricsLogger.Error(err, "failed to parse exporter timeout time format")
+				return newOpts, err
+			}
+
+			sink.exportTimeout = timeout
+		}
+
+		newOpts.pushOptions.sinks = append(newOpts.pushOptions.sinks, sink)
 	}
 
-	return newOpts
+	return newOpts, nil
 }
 
 // registerForHandler sets the global metrics registry to the provided Prometheus registerer.
@@ -155,7 +182,17 @@ func registerOTELHTTPexporter(otelOpts *[]metric.Option, opts registerOptions) e
 				return err
 			}
 
-			otelreader := metric.NewPeriodicReader(httpexporter)
+			periodOpts := []metric.PeriodicReaderOption{}
+			// If we do not set the interval or timeout for the exporter,
+			// we let the upstream set the default value for it.
+			if sink.exportInterval != 0 {
+				periodOpts = append(periodOpts, metric.WithInterval(sink.exportInterval))
+			}
+			if sink.exportTimeout != 0 {
+				periodOpts = append(periodOpts, metric.WithTimeout(sink.exportTimeout))
+			}
+
+			otelreader := metric.NewPeriodicReader(httpexporter, periodOpts...)
 			*otelOpts = append(*otelOpts, metric.WithReader(otelreader))
 			metricsLogger.Info("initialized otel http metrics push endpoint", "address", address)
 		}
@@ -178,7 +215,17 @@ func registerOTELgRPCexporter(otelOpts *[]metric.Option, opts registerOptions) e
 				return err
 			}
 
-			otelreader := metric.NewPeriodicReader(httpexporter)
+			periodOpts := []metric.PeriodicReaderOption{}
+			// If we do not set the interval or timeout for the exporter,
+			// we let the upstream set the default value for it.
+			if sink.exportInterval != 0 {
+				periodOpts = append(periodOpts, metric.WithInterval(sink.exportInterval))
+			}
+			if sink.exportTimeout != 0 {
+				periodOpts = append(periodOpts, metric.WithTimeout(sink.exportTimeout))
+			}
+
+			otelreader := metric.NewPeriodicReader(httpexporter, periodOpts...)
 			*otelOpts = append(*otelOpts, metric.WithReader(otelreader))
 			metricsLogger.Info("initialized otel grpc metrics push endpoint", "address", address)
 		}
@@ -200,7 +247,9 @@ type registerOptions struct {
 }
 
 type metricsSink struct {
-	protocol string
-	host     string
-	port     int32
+	protocol       string
+	host           string
+	port           int32
+	exportTimeout  time.Duration
+	exportInterval time.Duration
 }
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index a11a54391..829010b26 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -897,7 +897,7 @@ func (r *gatewayAPIReconciler) processBackendTLSPolicies(
 	}
 
 	// Add the referenced Secrets and ConfigMaps in BackendTLSPolicies to the resourceTree.
-	r.processBackendTLSPolicyConfigMapRefs(ctx, resourceTree, resourceMap)
+	r.processBackendTLSPolicyRefs(ctx, resourceTree, resourceMap)
 	return nil
 }
 
@@ -1575,27 +1575,49 @@ func (r *gatewayAPIReconciler) serviceImportCRDExists(mgr manager.Manager) bool
 	return serviceImportFound
 }
 
-func (r *gatewayAPIReconciler) processBackendTLSPolicyConfigMapRefs(ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) {
+func (r *gatewayAPIReconciler) processBackendTLSPolicyRefs(
+	ctx context.Context,
+	resourceTree *gatewayapi.Resources,
+	resourceMap *resourceMappings,
+) {
 	for _, policy := range resourceTree.BackendTLSPolicies {
 		tls := policy.Spec.Validation
 
 		if tls.CACertificateRefs != nil {
 			for _, caCertRef := range tls.CACertificateRefs {
-				if string(caCertRef.Kind) == gatewayapi.KindConfigMap {
+				// if kind is not Secret or ConfigMap, we skip early to avoid further calculation overhead
+				if string(caCertRef.Kind) == gatewayapi.KindConfigMap ||
+					string(caCertRef.Kind) == gatewayapi.KindSecret {
+
+					var err error
 					caRefNew := gwapiv1b1.SecretObjectReference{
 						Group:     gatewayapi.GroupPtr(string(caCertRef.Group)),
 						Kind:      gatewayapi.KindPtr(string(caCertRef.Kind)),
 						Name:      caCertRef.Name,
 						Namespace: gatewayapi.NamespacePtr(policy.Namespace),
 					}
-					if err := r.processConfigMapRef(
-						ctx,
-						resourceMap,
-						resourceTree,
-						gatewayapi.KindBackendTLSPolicy,
-						policy.Namespace,
-						policy.Name,
-						caRefNew); err != nil {
+					switch string(caCertRef.Kind) {
+					case gatewayapi.KindConfigMap:
+						err = r.processConfigMapRef(
+							ctx,
+							resourceMap,
+							resourceTree,
+							gatewayapi.KindBackendTLSPolicy,
+							policy.Namespace,
+							policy.Name,
+							caRefNew)
+
+					case gatewayapi.KindSecret:
+						err = r.processSecretRef(
+							ctx,
+							resourceMap,
+							resourceTree,
+							gatewayapi.KindBackendTLSPolicy,
+							policy.Namespace,
+							policy.Name,
+							caRefNew)
+					}
+					if err != nil {
 						// we don't return an error here, because we want to continue
 						// reconciling the rest of the ClientTrafficPolicies despite that this
 						// reference is invalid.
diff --git a/tools/crd-ref-docs/config.yaml b/tools/crd-ref-docs/config.yaml
index 2356eda59..f1920e2e2 100644
--- a/tools/crd-ref-docs/config.yaml
+++ b/tools/crd-ref-docs/config.yaml
@@ -4,7 +4,6 @@ processor:
     - "(EnvoyProxy)List$"
   # RE2 regular expressions describing type fields that should be excluded from the generated documentation.
   ignoreFields:
-    - "status$"
     - "TypeMeta$"
   customMarkers:
     - name: "notImplementedHide"
@@ -12,11 +11,27 @@ processor:
 
 render:
   # Version of Kubernetes to use when generating links to Kubernetes API documentation.
-  kubernetesVersion: 1.26
+  kubernetesVersion: 1.29
   knownTypes:
+    - name: BackendObjectReference
+      package: sigs.k8s.io/gateway-api/apis/v1
+      link: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference
     - name: SecretObjectReference
       package: sigs.k8s.io/gateway-api/apis/v1
       link: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference
     - name: LocalPolicyTargetReferenceWithSectionName
       package: sigs.k8s.io/gateway-api/apis/v1alpha2
       link: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName
+    - name: LocalPolicyTargetReference
+      package: sigs.k8s.io/gateway-api/apis/v1alpha2
+      link: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReference
+    - name: Duration
+      package: sigs.k8s.io/gateway-api/apis/v1
+      link: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration
+    - name: PolicyStatus
+      package: sigs.k8s.io/gateway-api/apis/v1alpha2
+      link: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus
+    - name: JSON
+      package: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
+      link: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io
+


Test patch:
diff --git a/internal/gatewayapi/status/conditions_test.go b/internal/gatewayapi/status/conditions_test.go
index 066dcabd2..74c66edf2 100644
--- a/internal/gatewayapi/status/conditions_test.go
+++ b/internal/gatewayapi/status/conditions_test.go
@@ -199,7 +199,7 @@ func TestError2ConditionMsg(t *testing.T) {
 		{
 			name:   "error with message",
 			err:    errors.New("something is wrong"),
-			expect: "Something is wrong",
+			expect: "Something is wrong.",
 		},
 	}
 	for _, tt := range testCases {
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.in.yaml b/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.in.yaml
new file mode 100644
index 000000000..b701ad980
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.in.yaml
@@ -0,0 +1,117 @@
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      name: gateway-btls
+      namespace: envoy-gateway
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: http
+          protocol: HTTP
+          port: 80
+          allowedRoutes:
+            namespaces:
+              from: All
+httpRoutes:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      name: httproute-btls
+      namespace: envoy-gateway
+    spec:
+      parentRefs:
+        - namespace: envoy-gateway
+          name: gateway-btls
+          sectionName: http
+      rules:
+        - matches:
+            - path:
+                type: Exact
+                value: "/exact"
+          backendRefs:
+            - name: http-backend
+              namespace: backends
+              port: 8080
+
+referenceGrants:
+  - apiVersion: gateway.networking.k8s.io/v1alpha2
+    kind: ReferenceGrant
+    metadata:
+      name: refg-route-svc
+      namespace: backends
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: HTTPRoute
+          namespace: envoy-gateway
+        - group: gateway.networking.k8s.io
+          kind: Gateway
+          namespace: envoy-gateway
+        - group: gateway.networking.k8s.io
+          kind: BackendTLSPolicy
+          namespace: policies
+      to:
+        - group: ""
+          kind: Service
+
+services:
+  - apiVersion: v1
+    kind: Service
+    metadata:
+      name: http-backend
+      namespace: backends
+    spec:
+      clusterIP: 10.11.12.13
+      ports:
+        - port: 8080
+          name: http
+          protocol: TCP
+          targetPort: 8080
+
+
+endpointSlices:
+  - apiVersion: discovery.k8s.io/v1
+    kind: EndpointSlice
+    metadata:
+      name: endpointslice-http-backend
+      namespace: backends
+      labels:
+        kubernetes.io/service-name: http-backend
+    addressType: IPv4
+    ports:
+      - name: http
+        protocol: TCP
+        port: 8080
+    endpoints:
+      - addresses:
+          - "10.244.0.11"
+        conditions:
+          ready: true
+
+secrets:
+  - apiVersion: v1
+    kind: Secret
+    metadata:
+      name: ca-secret
+      namespace: policies
+    data:
+      ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+backendTLSPolicies:
+  - apiVersion: gateway.networking.k8s.io/v1alpha2
+    kind: BackendTLSPolicy
+    metadata:
+      name: policy-btls
+      namespace: backends
+    spec:
+      targetRefs:
+        - group: ""
+          kind: Service
+          name: http-backend
+          sectionName: "8080"
+      validation:
+        caCertificateRefs:
+          - name: ca-secret
+            group: ""
+            kind: Secret
+        hostname: example.com
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.out.yaml
new file mode 100644
index 000000000..b817977e7
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtlspolicy-ca-only-secret.out.yaml
@@ -0,0 +1,165 @@
+backendTLSPolicies:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+  kind: BackendTLSPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-btls
+    namespace: backends
+  spec:
+    targetRefs:
+    - group: ""
+      kind: Service
+      name: http-backend
+      sectionName: "8080"
+    validation:
+      caCertificateRefs:
+      - group: ""
+        kind: Secret
+        name: ca-secret
+      hostname: example.com
+  status:
+    ancestors:
+    - ancestorRef:
+        name: gateway-btls
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-btls
+    namespace: envoy-gateway
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: http
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 1
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-btls
+    namespace: envoy-gateway
+  spec:
+    parentRefs:
+    - name: gateway-btls
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: http-backend
+        namespace: backends
+        port: 8080
+      matches:
+      - path:
+          type: Exact
+          value: /exact
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-btls
+        namespace: envoy-gateway
+        sectionName: http
+infraIR:
+  envoy-gateway/gateway-btls:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-btls/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-btls
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+      name: envoy-gateway/gateway-btls
+xdsIR:
+  envoy-gateway/gateway-btls:
+    accessLog:
+      text:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      name: envoy-gateway/gateway-btls/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          name: httproute/envoy-gateway/httproute-btls/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 10.244.0.11
+              port: 8080
+            protocol: HTTP
+            tls:
+              caCertificate:
+                certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                name: policy-btls/backends-ca
+              sni: example.com
+            weight: 1
+        hostname: '*'
+        isHTTP2: false
+        name: httproute/envoy-gateway/httproute-btls/rule/0/match/0/*
+        pathMatch:
+          distinct: false
+          exact: /exact
+          name: ""
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
index e5c997f27..a99860bb1 100644
--- a/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
+++ b/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
@@ -25,7 +25,7 @@ backendTLSPolicies:
         sectionName: http
       conditions:
       - lastTransitionTime: null
-        message: No ca found in configmap no-ca-cmap
+        message: No ca found in configmap no-ca-cmap.
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
index 223ccf273..b60218d10 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml
@@ -22,7 +22,7 @@ backendTrafficPolicies:
         sectionName: http
       conditions:
       - lastTransitionTime: null
-        message: 'CircuitBreaker: invalid MaxRequestsPerConnection value -1'
+        message: 'CircuitBreaker: invalid MaxRequestsPerConnection value -1.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -50,7 +50,7 @@ backendTrafficPolicies:
         sectionName: http
       conditions:
       - lastTransitionTime: null
-        message: 'CircuitBreaker: invalid MaxParallelRetries value -1'
+        message: 'CircuitBreaker: invalid MaxParallelRetries value -1.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -77,7 +77,7 @@ backendTrafficPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'CircuitBreaker: invalid MaxConnections value -1'
+        message: 'CircuitBreaker: invalid MaxConnections value -1.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
index 5aceec2a5..68c2812ac 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml
@@ -47,7 +47,7 @@ backendTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: 'RateLimit: local rateLimit rule limit unit must be a multiple of
-          the default limit unit'
+          the default limit unit.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
index d286951ec..4a3317ac1 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml
@@ -43,7 +43,7 @@ backendTrafficPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'RateLimit: local rateLimit does not support distinct HeaderMatch'
+        message: 'RateLimit: local rateLimit does not support distinct HeaderMatch.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
index 9d82dac48..99f5cfe8c 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml
@@ -50,7 +50,7 @@ backendTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: 'RateLimit: local rateLimit can not have more than one rule without
-          clientSelectors'
+          clientSelectors.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
index 99115522e..f412c2a86 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml
@@ -34,7 +34,7 @@ backendTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: 'RateLimit: regex "*.illegal.regex" is invalid: error parsing regexp:
-          missing argument to repetition operator: `*`'
+          missing argument to repetition operator: `*`.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
index c32fa1ae2..1bcc74258 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml
@@ -25,7 +25,7 @@ backendTrafficPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'Timeout: invalid MaxConnectionDuration value 22mib'
+        message: 'Timeout: invalid MaxConnectionDuration value 22mib.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-format-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-format-error.out.yaml
index 8a366de05..246db1423 100755
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-format-error.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-format-error.out.yaml
@@ -23,7 +23,7 @@ clientTrafficPolicies:
         sectionName: http-1
       conditions:
       - lastTransitionTime: null
-        message: Invalid BufferLimit value 500m
+        message: 'Connection: invalid BufferLimit value 500m.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-out-of-range-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-out-of-range-error.out.yaml
index 9f983a0d2..cabe1f7a6 100755
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-out-of-range-error.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-buffer-limit-with-out-of-range-error.out.yaml
@@ -23,7 +23,8 @@ clientTrafficPolicies:
         sectionName: http-1
       conditions:
       - lastTransitionTime: null
-        message: BufferLimit value 100G is out of range, must be between 0 and 4294967295
+        message: 'Connection: BufferLimit value 100G is out of range, must be between
+          0 and 4294967295.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-connection-limit-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-connection-limit-error.out.yaml
index 5eb39d934..eaea65e56 100755
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-connection-limit-error.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-connection-limit-error.out.yaml
@@ -25,7 +25,7 @@ clientTrafficPolicies:
         sectionName: http-1
       conditions:
       - lastTransitionTime: null
-        message: Invalid CloseDelay value 10mib
+        message: 'Connection: invalid CloseDelay value 10mib.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
index d0e2660dc..4a8a3b98f 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
@@ -83,7 +83,8 @@ clientTrafficPolicies:
         sectionName: http-3
       conditions:
       - lastTransitionTime: null
-        message: Can't set http10 default host on listener with only wildcard hostnames
+        message: 'HTTP1: cannot set http10 default host on listener with only wildcard
+          hostnames.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http2.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http2.out.yaml
index e94e1ffed..cf410dffe 100755
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-http2.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http2.out.yaml
@@ -57,8 +57,8 @@ clientTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: |-
-          InitialStreamWindowSize value 1Ki is out of range, must be between 65535 and 2147483647
-          InitialConnectionWindowSize value 1Ti is out of range, must be between 65535 and 2147483647
+          HTTP2: InitialStreamWindowSize value 1Ki is out of range, must be between 65535 and 2147483647
+          InitialConnectionWindowSize value 1Ti is out of range, must be between 65535 and 2147483647.
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-idle-timeout-with-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-idle-timeout-with-error.out.yaml
index 18b814b82..6989cb91d 100755
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-idle-timeout-with-error.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-idle-timeout-with-error.out.yaml
@@ -22,7 +22,7 @@ clientTrafficPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'Time: unknown unit "sec" in duration "10sec"'
+        message: 'Timeout: time: unknown unit "sec" in duration "10sec".'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml
index d162dce4b..7efaef7eb 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml
@@ -22,7 +22,7 @@ clientTrafficPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'Time: unknown unit "sec" in duration "5sec"'
+        message: 'Timeout: time: unknown unit "sec" in duration "5sec".'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/conflicting-policies.out.yaml b/internal/gatewayapi/testdata/conflicting-policies.out.yaml
index d6a50d7db..0af25b10a 100644
--- a/internal/gatewayapi/testdata/conflicting-policies.out.yaml
+++ b/internal/gatewayapi/testdata/conflicting-policies.out.yaml
@@ -23,7 +23,7 @@ clientTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: ClientTrafficPolicy is being applied to multiple http (non https)
-          listeners (default/gateway-1/http) on the same port, which is not allowed
+          listeners (default/gateway-1/http) on the same port, which is not allowed.
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml
index 27619e60e..76ce25c20 100755
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml
@@ -23,7 +23,7 @@ envoyExtensionPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: TCP Port 4000 not found on service default/grpc-backend
+        message: 'ExtProcs: TCP Port 4000 not found on service default/grpc-backend.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml
index ac556bd8a..c8d26813c 100755
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml
@@ -22,8 +22,8 @@ envoyExtensionPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: A valid port number corresponding to a port on the Service must be
-          specified
+        message: 'ExtProcs: a valid port number corresponding to a port on the Service
+          must be specified.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml
index 09b3ecdcc..50148ea73 100755
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml
@@ -24,8 +24,8 @@ envoyExtensionPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Backend ref to Service envoy-gateway/grpc-backend not permitted by
-          any ReferenceGrant
+        message: 'ExtProcs: backend ref to Service envoy-gateway/grpc-backend not
+          permitted by any ReferenceGrant.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml
index 630a246f8..7e5e5aba4 100755
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml
@@ -24,7 +24,7 @@ envoyExtensionPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Service envoy-gateway/grpc-backend not found
+        message: 'ExtProcs: service envoy-gateway/grpc-backend not found.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
index bd25d7bc6..4b5fc9ae9 100644
--- a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml
@@ -25,7 +25,7 @@ backendTrafficPolicies:
         sectionName: http
       conditions:
       - lastTransitionTime: null
-        message: 'Timeout: invalid ConnectTimeout value 20kib'
+        message: 'Timeout: invalid ConnectTimeout value 20kib.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-regex.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-regex.out.yaml
index a8e06b4fa..c8285fb3e 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-regex.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-regex.out.yaml
@@ -103,7 +103,7 @@ httpRoutes:
     - conditions:
       - lastTransitionTime: null
         message: 'Regex "*.foo.bar.com" is invalid: error parsing regexp: missing
-          argument to repetition operator: `*`'
+          argument to repetition operator: `*`.'
         reason: UnsupportedValue
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml
index 7cae3475b..2b3440d9a 100644
--- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-multiple-rules.out.yaml
@@ -93,7 +93,7 @@ httpRoutes:
     - conditions:
       - lastTransitionTime: null
         message: 'Regex "*regex*" is invalid: error parsing regexp: missing argument
-          to repetition operator: `*`'
+          to repetition operator: `*`.'
         reason: UnsupportedValue
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/merge-with-isolated-policies-2.out.yaml b/internal/gatewayapi/testdata/merge-with-isolated-policies-2.out.yaml
index 5c74b388d..d22f2ed11 100755
--- a/internal/gatewayapi/testdata/merge-with-isolated-policies-2.out.yaml
+++ b/internal/gatewayapi/testdata/merge-with-isolated-policies-2.out.yaml
@@ -55,7 +55,7 @@ clientTrafficPolicies:
       conditions:
       - lastTransitionTime: null
         message: ClientTrafficPolicy is being applied to multiple http (non https)
-          listeners (default/gateway-2/http-2) on the same port, which is not allowed
+          listeners (default/gateway-2/http-2) on the same port, which is not allowed.
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml
index 0d8bb167f..582db7cf2 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml
@@ -125,7 +125,7 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: TCP Port 80 not found on service default/http-backend
+        message: 'ExtAuth: TCP Port 80 not found on service default/http-backend.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-port.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-port.out.yaml
index eb6859257..fa9d38b25 100755
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-port.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-port.out.yaml
@@ -124,8 +124,8 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: A valid port number corresponding to a port on the Service must be
-          specified
+        message: 'ExtAuth: a valid port number corresponding to a port on the Service
+          must be specified.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml
index 648d8567a..9afc90b09 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml
@@ -125,8 +125,8 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Backend ref to Service envoy-gateway/http-backend not permitted by
-          any ReferenceGrant
+        message: 'ExtAuth: backend ref to Service envoy-gateway/http-backend not permitted
+          by any ReferenceGrant.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
index 62ac5dabd..cc079ddf6 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml
@@ -125,7 +125,7 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Service default/http-backend not found
+        message: 'ExtAuth: service default/http-backend not found.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml
index 6c9172f65..f2ca05d14 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml
@@ -173,7 +173,7 @@ securityPolicies:
         sectionName: http
       conditions:
       - lastTransitionTime: null
-        message: Secret default/client2-secret does not exist
+        message: 'OIDC: secret default/client2-secret does not exist.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -217,7 +217,7 @@ securityPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: Secret envoy-gateway/client1-secret does not exist
+        message: 'OIDC: secret envoy-gateway/client1-secret does not exist.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml
index d2a6d6afa..1102e64d4 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml
@@ -85,8 +85,8 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: 'Error fetching endpoints from issuer: invalid character ''<'' looking
-          for beginning of value'
+        message: 'OIDC: error fetching endpoints from issuer: invalid character ''<''
+          looking for beginning of value.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml
index 2ea3ac242..259908a1a 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml
@@ -197,7 +197,7 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Secret default/client1-secret does not exist
+        message: 'OIDC: secret default/client1-secret does not exist.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -234,7 +234,7 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Secret ref namespace must be unspecified/empty or default
+        message: 'OIDC: secret ref namespace must be unspecified/empty or default.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -270,7 +270,7 @@ securityPolicies:
         namespace: default
       conditions:
       - lastTransitionTime: null
-        message: Client secret not found in secret default/client3-secret
+        message: 'OIDC: client secret not found in secret default/client3-secret.'
         reason: Invalid
         status: "False"
         type: Accepted
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index b7dd708a3..522454449 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -117,8 +117,8 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | Timeout defines the time to wait for a health check response. |
-| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | Interval defines the time between active health checks. |
+| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | Timeout defines the time to wait for a health check response. |
+| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | Interval defines the time between active health checks. |
 | `unhealthyThreshold` | _integer_ |  false  | UnhealthyThreshold defines the number of unhealthy health checks required before a backend host is marked unhealthy. |
 | `healthyThreshold` | _integer_ |  false  | HealthyThreshold defines the number of healthy health checks required before a backend host is marked healthy. |
 | `type` | _[ActiveHealthCheckerType](#activehealthcheckertype)_ |  true  | Type defines the type of health checker. |
@@ -215,8 +215,8 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `baseInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  true  | BaseInterval is the base interval between retries. |
-| `maxInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | MaxInterval is the maximum interval between retries. This parameter is optional, but must be greater than or equal to the base_interval if set.<br />The default is 10 times the base_interval |
+| `baseInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | BaseInterval is the base interval between retries. |
+| `maxInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | MaxInterval is the maximum interval between retries. This parameter is optional, but must be greater than or equal to the base_interval if set.<br />The default is 10 times the base_interval |
 
 
 #### Backend
@@ -233,8 +233,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`Backend`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[BackendSpec](#backendspec)_ |  true  | Spec defines the desired state of Backend. |
+| `status` | _[BackendStatus](#backendstatus)_ |  true  | Status defines the current status of Backend. |
 
 
 
@@ -270,7 +271,7 @@ BackendList contains a list of Backend resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`BackendList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[Backend](#backend) array_ |  true  |  |
 
 
@@ -311,6 +312,18 @@ _Appears in:_
 | `appProtocols` | _[AppProtocolType](#appprotocoltype) array_ |  false  | AppProtocols defines the application protocols to be supported when connecting to the backend. |
 
 
+#### BackendStatus
+
+
+
+BackendStatus defines the state of Backend
+
+_Appears in:_
+- [Backend](#backend)
+
+| Field | Type | Required | Description |
+| ---   | ---  | ---      | ---         |
+| `conditions` | _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#condition-v1-meta) array_ |  false  | Conditions describe the current conditions of the Backend. |
 
 
 #### BackendTLSConfig
@@ -347,8 +360,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`BackendTrafficPolicy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[BackendTrafficPolicySpec](#backendtrafficpolicyspec)_ |  true  | spec defines the desired state of BackendTrafficPolicy. |
+| `status` | _[PolicyStatus](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus)_ |  true  | status defines the current status of BackendTrafficPolicy. |
 
 
 #### BackendTrafficPolicyConnection
@@ -377,7 +391,7 @@ BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`BackendTrafficPolicyList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[BackendTrafficPolicy](#backendtrafficpolicy) array_ |  true  |  |
 
 
@@ -450,7 +464,7 @@ _Appears in:_
 | `allowMethods` | _string array_ |  true  | AllowMethods defines the methods that are allowed to make requests. |
 | `allowHeaders` | _string array_ |  true  | AllowHeaders defines the headers that are allowed to be sent with requests. |
 | `exposeHeaders` | _string array_ |  true  | ExposeHeaders defines the headers that can be exposed in the responses. |
-| `maxAge` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  true  | MaxAge defines how long the results of a preflight request can be cached. |
+| `maxAge` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | MaxAge defines how long the results of a preflight request can be cached. |
 | `allowCredentials` | _boolean_ |  true  | AllowCredentials indicates whether a request can include user credentials<br />like cookies, authentication headers, or TLS client certificates. |
 
 
@@ -551,8 +565,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`ClientTrafficPolicy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[ClientTrafficPolicySpec](#clienttrafficpolicyspec)_ |  true  | Spec defines the desired state of ClientTrafficPolicy. |
+| `status` | _[PolicyStatus](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus)_ |  true  | Status defines the current status of ClientTrafficPolicy. |
 
 
 #### ClientTrafficPolicyList
@@ -567,7 +582,7 @@ ClientTrafficPolicyList contains a list of ClientTrafficPolicy resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`ClientTrafficPolicyList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[ClientTrafficPolicy](#clienttrafficpolicy) array_ |  true  |  |
 
 
@@ -668,7 +683,7 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `value` | _integer_ |  true  | Value of the maximum concurrent connections limit.<br />When the limit is reached, incoming connections will be closed after the CloseDelay duration.<br />Default: unlimited. |
-| `closeDelay` | _[Duration](#duration)_ |  false  | CloseDelay defines the delay to use before closing connections that are rejected<br />once the limit value is reached.<br />Default: none. |
+| `closeDelay` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | CloseDelay defines the delay to use before closing connections that are rejected<br />once the limit value is reached.<br />Default: none. |
 
 
 #### ConsistentHash
@@ -781,8 +796,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`EnvoyExtensionPolicy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[EnvoyExtensionPolicySpec](#envoyextensionpolicyspec)_ |  true  | Spec defines the desired state of EnvoyExtensionPolicy. |
+| `status` | _[PolicyStatus](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus)_ |  true  | Status defines the current status of EnvoyExtensionPolicy. |
 
 
 #### EnvoyExtensionPolicyList
@@ -797,7 +813,7 @@ EnvoyExtensionPolicyList contains a list of EnvoyExtensionPolicy resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`EnvoyExtensionPolicyList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[EnvoyExtensionPolicy](#envoyextensionpolicy) array_ |  true  |  |
 
 
@@ -1049,6 +1065,8 @@ _Appears in:_
 | `host` | _string_ |  true  | Host define the sink service hostname. |
 | `protocol` | _string_ |  true  | Protocol define the sink service protocol. |
 | `port` | _integer_ |  false  | Port defines the port the sink service is exposed on. |
+| `exportInterval` | _[Duration](#duration)_ |  true  | ExportInterval configures the intervening time between exports for a<br />Sink. This option overrides any value set for the<br />OTEL_METRIC_EXPORT_INTERVAL environment variable.<br />If ExportInterval is less than or equal to zero, 60 seconds<br />is used as the default. |
+| `exportTimeout` | _[Duration](#duration)_ |  true  | ExportTimeout configures the time a Sink waits for an export to<br />complete before canceling it. This option overrides any value set for the<br />OTEL_METRIC_EXPORT_TIMEOUT environment variable.<br />If ExportTimeout is less than or equal to zero, 30 seconds<br />is used as the default. |
 
 
 #### EnvoyGatewayPrometheusProvider
@@ -1165,8 +1183,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`EnvoyPatchPolicy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[EnvoyPatchPolicySpec](#envoypatchpolicyspec)_ |  true  | Spec defines the desired state of EnvoyPatchPolicy. |
+| `status` | _[PolicyStatus](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus)_ |  true  | Status defines the current status of EnvoyPatchPolicy. |
 
 
 #### EnvoyPatchPolicyList
@@ -1181,7 +1200,7 @@ EnvoyPatchPolicyList contains a list of EnvoyPatchPolicy resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`EnvoyPatchPolicyList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[EnvoyPatchPolicy](#envoypatchpolicy) array_ |  true  |  |
 
 
@@ -1198,7 +1217,7 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `type` | _[EnvoyPatchType](#envoypatchtype)_ |  true  | Type decides the type of patch.<br />Valid EnvoyPatchType values are "JSONPatch". |
 | `jsonPatches` | _[EnvoyJSONPatchConfig](#envoyjsonpatchconfig) array_ |  false  | JSONPatch defines the JSONPatch configuration. |
-| `targetRef` | _[LocalPolicyTargetReference](#localpolicytargetreference)_ |  true  | TargetRef is the name of the Gateway API resource this policy<br />is being attached to.<br />By default, attaching to Gateway is supported and<br />when mergeGateways is enabled it should attach to GatewayClass.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway<br />TargetRef |
+| `targetRef` | _[LocalPolicyTargetReference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReference)_ |  true  | TargetRef is the name of the Gateway API resource this policy<br />is being attached to.<br />By default, attaching to Gateway is supported and<br />when mergeGateways is enabled it should attach to GatewayClass.<br />This Policy and the TargetRef MUST be in the same namespace<br />for this Policy to have effect and be applied to the Gateway<br />TargetRef |
 | `priority` | _integer_ |  true  | Priority of the EnvoyPatchPolicy.<br />If multiple EnvoyPatchPolicies are applied to the same<br />TargetRef, they will be applied in the ascending order of<br />the priority i.e. int32.min has the highest priority and<br />int32.max has the lowest priority.<br />Defaults to 0. |
 
 
@@ -1228,8 +1247,9 @@ EnvoyProxy is the schema for the envoyproxies API.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`EnvoyProxy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[EnvoyProxySpec](#envoyproxyspec)_ |  true  | EnvoyProxySpec defines the desired state of EnvoyProxy. |
+| `status` | _[EnvoyProxyStatus](#envoyproxystatus)_ |  true  | EnvoyProxyStatus defines the actual state of EnvoyProxy. |
 
 
 #### EnvoyProxyKubernetesProvider
@@ -1289,6 +1309,16 @@ _Appears in:_
 | `backendTLS` | _[BackendTLSConfig](#backendtlsconfig)_ |  false  | BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends.<br />These settings are applied on backends for which TLS policies are specified. |
 
 
+#### EnvoyProxyStatus
+
+
+
+EnvoyProxyStatus defines the observed state of EnvoyProxy. This type is not implemented
+until https://github.com/envoyproxy/gateway/issues/1007 is fixed.
+
+_Appears in:_
+- [EnvoyProxy](#envoyproxy)
+
 
 
 #### EnvoyResourceType
@@ -1337,7 +1367,7 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `backendRefs` | _[BackendRef](#backendref) array_ |  true  | BackendRefs defines the configuration of the external processing service |
-| `messageTimeout` | _[Duration](#duration)_ |  false  | MessageTimeout is the timeout for a response to be returned from the external processor<br />Default: 200ms |
+| `messageTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | MessageTimeout is the timeout for a response to be returned from the external processor<br />Default: 200ms |
 | `failOpen` | _boolean_ |  false  | FailOpen defines if requests or responses that cannot be processed due to connectivity to the<br />external processor are terminated or passed-through.<br />Default: false |
 | `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ |  false  | ProcessingMode defines how request and response body is processed<br />Default: header and body are not sent to the external processor |
 
@@ -1511,7 +1541,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `fixedDelay` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  true  | FixedDelay specifies the fixed delay duration |
+| `fixedDelay` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | FixedDelay specifies the fixed delay duration |
 | `percentage` | _float_ |  false  | Percentage specifies the percentage of requests to be delayed. Default 100%, if set 0, no requests will be delayed. Accuracy to 0.0001%. |
 
 
@@ -1558,7 +1588,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `backendRef` | _[BackendObjectReference](#backendobjectreference)_ |  true  | BackendRef references a Kubernetes object that represents the<br />backend server to which the authorization request will be sent.<br />Only service Kind is supported for now. |
+| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ |  true  | BackendRef references a Kubernetes object that represents the<br />backend server to which the authorization request will be sent.<br />Only service Kind is supported for now. |
 
 
 #### Gateway
@@ -1705,8 +1735,8 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `requestReceivedTimeout` | _[Duration](#duration)_ |  false  | RequestReceivedTimeout is the duration envoy waits for the complete request reception. This timer starts upon request<br />initiation and stops when either the last byte of the request is sent upstream or when the response begins. |
-| `idleTimeout` | _[Duration](#duration)_ |  false  | IdleTimeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.<br />Default: 1 hour. |
+| `requestReceivedTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | RequestReceivedTimeout is the duration envoy waits for the complete request reception. This timer starts upon request<br />initiation and stops when either the last byte of the request is sent upstream or when the response begins. |
+| `idleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | IdleTimeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.<br />Default: 1 hour. |
 
 
 #### HTTPExtAuthService
@@ -1720,7 +1750,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `backendRef` | _[BackendObjectReference](#backendobjectreference)_ |  true  | BackendRef references a Kubernetes object that represents the<br />backend server to which the authorization request will be sent.<br />Only service Kind is supported for now. |
+| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ |  true  | BackendRef references a Kubernetes object that represents the<br />backend server to which the authorization request will be sent.<br />Only service Kind is supported for now. |
 | `path` | _string_ |  true  | Path is the path of the HTTP External Authorization service.<br />If path is specified, the authorization request will be sent to that path,<br />or else the authorization request will be sent to the root path. |
 | `headersToBackend` | _string array_ |  false  | HeadersToBackend are the authorization response headers that will be added<br />to the original client request before sending it to the backend server.<br />Note that coexisting headers will be overridden.<br />If not specified, no authorization response headers will be added to the<br />original client request. |
 
@@ -1748,8 +1778,8 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `connectionIdleTimeout` | _[Duration](#duration)_ |  false  | The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.<br />Default: 1 hour. |
-| `maxConnectionDuration` | _[Duration](#duration)_ |  false  | The maximum duration of an HTTP connection.<br />Default: unlimited. |
+| `connectionIdleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.<br />Default: 1 hour. |
+| `maxConnectionDuration` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | The maximum duration of an HTTP connection.<br />Default: unlimited. |
 
 
 #### HTTPWasmCodeSource
@@ -1893,7 +1923,7 @@ _Appears in:_
 | `op` | _[JSONPatchOperationType](#jsonpatchoperationtype)_ |  true  | Op is the type of operation to perform |
 | `path` | _string_ |  true  | Path is the location of the target document/field where the operation will be performed<br />Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. |
 | `from` | _string_ |  false  | From is the source location of the value to be copied or moved. Only valid<br />for move or copy operations<br />Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. |
-| `value` | _[JSON](#json)_ |  false  | Value is the new value of the path location. The value is only used by<br />the `add` and `replace` operations. |
+| `value` | _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io)_ |  false  | Value is the new value of the path location. The value is only used by<br />the `add` and `replace` operations. |
 
 
 #### JSONPatchOperationType
@@ -1987,11 +2017,11 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `env` | _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#envvar-v1-core) array_ |  false  | List of environment variables to set in the container. |
-| `resources` | _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#resourcerequirements-v1-core)_ |  false  | Resources required by this container.<br />More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
-| `securityContext` | _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core)_ |  false  | SecurityContext defines the security options the container should be run with.<br />If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.<br />More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ |
+| `env` | _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#envvar-v1-core) array_ |  false  | List of environment variables to set in the container. |
+| `resources` | _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#resourcerequirements-v1-core)_ |  false  | Resources required by this container.<br />More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
+| `securityContext` | _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#securitycontext-v1-core)_ |  false  | SecurityContext defines the security options the container should be run with.<br />If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.<br />More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ |
 | `image` | _string_ |  false  | Image specifies the EnvoyProxy container image to be used, instead of the default image. |
-| `volumeMounts` | _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumemount-v1-core) array_ |  false  | VolumeMounts are volumes to mount into the container's filesystem.<br />Cannot be updated. |
+| `volumeMounts` | _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#volumemount-v1-core) array_ |  false  | VolumeMounts are volumes to mount into the container's filesystem.<br />Cannot be updated. |
 
 
 #### KubernetesDaemonSetSpec
@@ -2006,7 +2036,7 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `patch` | _[KubernetesPatchSpec](#kubernetespatchspec)_ |  false  | Patch defines how to perform the patch operation to daemonset |
-| `strategy` | _[DaemonSetUpdateStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#daemonsetupdatestrategy-v1-apps)_ |  false  | The daemonset strategy to use to replace existing pods with new ones. |
+| `strategy` | _[DaemonSetUpdateStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#daemonsetupdatestrategy-v1-apps)_ |  false  | The daemonset strategy to use to replace existing pods with new ones. |
 | `pod` | _[KubernetesPodSpec](#kubernetespodspec)_ |  false  | Pod defines the desired specification of pod. |
 | `container` | _[KubernetesContainerSpec](#kubernetescontainerspec)_ |  false  | Container defines the desired specification of main container. |
 
@@ -2037,10 +2067,10 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `patch` | _[KubernetesPatchSpec](#kubernetespatchspec)_ |  false  | Patch defines how to perform the patch operation to deployment |
 | `replicas` | _integer_ |  false  | Replicas is the number of desired pods. Defaults to 1. |
-| `strategy` | _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#deploymentstrategy-v1-apps)_ |  false  | The deployment strategy to use to replace existing pods with new ones. |
+| `strategy` | _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#deploymentstrategy-v1-apps)_ |  false  | The deployment strategy to use to replace existing pods with new ones. |
 | `pod` | _[KubernetesPodSpec](#kubernetespodspec)_ |  false  | Pod defines the desired specification of pod. |
 | `container` | _[KubernetesContainerSpec](#kubernetescontainerspec)_ |  false  | Container defines the desired specification of main container. |
-| `initContainers` | _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#container-v1-core) array_ |  false  | List of initialization containers belonging to the pod.<br />More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ |
+| `initContainers` | _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#container-v1-core) array_ |  false  | List of initialization containers belonging to the pod.<br />More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ |
 
 
 #### KubernetesHorizontalPodAutoscalerSpec
@@ -2059,8 +2089,8 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `minReplicas` | _integer_ |  false  | minReplicas is the lower limit for the number of replicas to which the autoscaler<br />can scale down. It defaults to 1 replica. |
 | `maxReplicas` | _integer_ |  true  | maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up.<br />It cannot be less that minReplicas. |
-| `metrics` | _[MetricSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#metricspec-v2-autoscaling) array_ |  false  | metrics contains the specifications for which to use to calculate the<br />desired replica count (the maximum replica count across all metrics will<br />be used).<br />If left empty, it defaults to being based on CPU utilization with average on 80% usage. |
-| `behavior` | _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#horizontalpodautoscalerbehavior-v2-autoscaling)_ |  false  | behavior configures the scaling behavior of the target<br />in both Up and Down directions (scaleUp and scaleDown fields respectively).<br />If not set, the default HPAScalingRules for scale up and scale down are used.<br />See k8s.io.autoscaling.v2.HorizontalPodAutoScalerBehavior. |
+| `metrics` | _[MetricSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#metricspec-v2-autoscaling) array_ |  false  | metrics contains the specifications for which to use to calculate the<br />desired replica count (the maximum replica count across all metrics will<br />be used).<br />If left empty, it defaults to being based on CPU utilization with average on 80% usage. |
+| `behavior` | _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#horizontalpodautoscalerbehavior-v2-autoscaling)_ |  false  | behavior configures the scaling behavior of the target<br />in both Up and Down directions (scaleUp and scaleDown fields respectively).<br />If not set, the default HPAScalingRules for scale up and scale down are used.<br />See k8s.io.autoscaling.v2.HorizontalPodAutoScalerBehavior. |
 
 
 #### KubernetesPatchSpec
@@ -2077,7 +2107,7 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `type` | _[MergeType](#mergetype)_ |  false  | Type is the type of merge operation to perform<br /><br />By default, StrategicMerge is used as the patch type. |
-| `value` | _[JSON](#json)_ |  true  | Object contains the raw configuration for merged object |
+| `value` | _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io)_ |  true  | Object contains the raw configuration for merged object |
 
 
 #### KubernetesPodSpec
@@ -2094,13 +2124,13 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `annotations` | _object (keys:string, values:string)_ |  false  | Annotations are the annotations that should be appended to the pods.<br />By default, no pod annotations are appended. |
 | `labels` | _object (keys:string, values:string)_ |  false  | Labels are the additional labels that should be tagged to the pods.<br />By default, no additional pod labels are tagged. |
-| `securityContext` | _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core)_ |  false  | SecurityContext holds pod-level security attributes and common container settings.<br />Optional: Defaults to empty.  See type description for default values of each field. |
-| `affinity` | _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#affinity-v1-core)_ |  false  | If specified, the pod's scheduling constraints. |
-| `tolerations` | _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#toleration-v1-core) array_ |  false  | If specified, the pod's tolerations. |
-| `volumes` | _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) array_ |  false  | Volumes that can be mounted by containers belonging to the pod.<br />More info: https://kubernetes.io/docs/concepts/storage/volumes |
-| `imagePullSecrets` | _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#localobjectreference-v1-core) array_ |  false  | ImagePullSecrets is an optional list of references to secrets<br />in the same namespace to use for pulling any of the images used by this PodSpec.<br />If specified, these secrets will be passed to individual puller implementations for them to use.<br />More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod |
+| `securityContext` | _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#podsecuritycontext-v1-core)_ |  false  | SecurityContext holds pod-level security attributes and common container settings.<br />Optional: Defaults to empty.  See type description for default values of each field. |
+| `affinity` | _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#affinity-v1-core)_ |  false  | If specified, the pod's scheduling constraints. |
+| `tolerations` | _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#toleration-v1-core) array_ |  false  | If specified, the pod's tolerations. |
+| `volumes` | _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#volume-v1-core) array_ |  false  | Volumes that can be mounted by containers belonging to the pod.<br />More info: https://kubernetes.io/docs/concepts/storage/volumes |
+| `imagePullSecrets` | _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#localobjectreference-v1-core) array_ |  false  | ImagePullSecrets is an optional list of references to secrets<br />in the same namespace to use for pulling any of the images used by this PodSpec.<br />If specified, these secrets will be passed to individual puller implementations for them to use.<br />More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod |
 | `nodeSelector` | _object (keys:string, values:string)_ |  false  | NodeSelector is a selector which must be true for the pod to fit on a node.<br />Selector which must match a node's labels for the pod to be scheduled on that node.<br />More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ |
-| `topologySpreadConstraints` | _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#topologyspreadconstraint-v1-core) array_ |  false  | TopologySpreadConstraints describes how a group of pods ought to spread across topology<br />domains. Scheduler will schedule pods in a way which abides by the constraints.<br />All topologySpreadConstraints are ANDed. |
+| `topologySpreadConstraints` | _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#topologyspreadconstraint-v1-core) array_ |  false  | TopologySpreadConstraints describes how a group of pods ought to spread across topology<br />domains. Scheduler will schedule pods in a way which abides by the constraints.<br />All topologySpreadConstraints are ANDed. |
 
 
 #### KubernetesServiceSpec
@@ -2137,7 +2167,7 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `type` | _[KubernetesWatchModeType](#kuberneteswatchmodetype)_ |  true  | Type indicates what watch mode to use. KubernetesWatchModeTypeNamespaces and<br />KubernetesWatchModeTypeNamespaceSelector are currently supported<br />By default, when this field is unset or empty, Envoy Gateway will watch for input namespaced resources<br />from all namespaces. |
 | `namespaces` | _string array_ |  true  | Namespaces holds the list of namespaces that Envoy Gateway will watch for namespaced scoped<br />resources such as Gateway, HTTPRoute and Service.<br />Note that Envoy Gateway will continue to reconcile relevant cluster scoped resources such as<br />GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelector must be set. |
-| `namespaceSelector` | _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#labelselector-v1-meta)_ |  true  | NamespaceSelector holds the label selector used to dynamically select namespaces.<br />Envoy Gateway will watch for namespaces matching the specified label selector.<br />Precisely one of Namespaces and NamespaceSelector must be set. |
+| `namespaceSelector` | _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#labelselector-v1-meta)_ |  true  | NamespaceSelector holds the label selector used to dynamically select namespaces.<br />Envoy Gateway will watch for namespaces matching the specified label selector.<br />Precisely one of Namespaces and NamespaceSelector must be set. |
 
 
 #### KubernetesWatchModeType
@@ -2162,9 +2192,9 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `leaseDuration` | _[Duration](#duration)_ |  true  | LeaseDuration defines the time non-leader contenders will wait before attempting to claim leadership.<br />It's based on the timestamp of the last acknowledged signal. The default setting is 15 seconds. |
-| `renewDeadline` | _[Duration](#duration)_ |  true  | RenewDeadline represents the time frame within which the current leader will attempt to renew its leadership<br />status before relinquishing its position. The default setting is 10 seconds. |
-| `retryPeriod` | _[Duration](#duration)_ |  true  | RetryPeriod denotes the interval at which LeaderElector clients should perform action retries.<br />The default setting is 2 seconds. |
+| `leaseDuration` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  true  | LeaseDuration defines the time non-leader contenders will wait before attempting to claim leadership.<br />It's based on the timestamp of the last acknowledged signal. The default setting is 15 seconds. |
+| `renewDeadline` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  true  | RenewDeadline represents the time frame within which the current leader will attempt to renew its leadership<br />status before relinquishing its position. The default setting is 10 seconds. |
+| `retryPeriod` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  true  | RetryPeriod denotes the interval at which LeaderElector clients should perform action retries.<br />The default setting is 2 seconds. |
 | `disable` | _boolean_ |  true  | Disable provides the option to turn off leader election, which is enabled by default. |
 
 
@@ -2354,11 +2384,11 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `splitExternalLocalOriginErrors` | _boolean_ |  false  | SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. |
-| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | Interval defines the time between passive health checks. |
+| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | Interval defines the time between passive health checks. |
 | `consecutiveLocalOriginFailures` | _integer_ |  false  | ConsecutiveLocalOriginFailures sets the number of consecutive local origin failures triggering ejection.<br />Parameter takes effect only when split_external_local_origin_errors is set to true. |
 | `consecutiveGatewayErrors` | _integer_ |  false  | ConsecutiveGatewayErrors sets the number of consecutive gateway errors triggering ejection. |
 | `consecutive5XxErrors` | _integer_ |  false  | Consecutive5xxErrors sets the number of consecutive 5xx errors triggering ejection. |
-| `baseEjectionTime` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | BaseEjectionTime defines the base duration for which a host will be ejected on consecutive failures. |
+| `baseEjectionTime` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | BaseEjectionTime defines the base duration for which a host will be ejected on consecutive failures. |
 | `maxEjectionPercent` | _integer_ |  false  | MaxEjectionPercent sets the maximum percentage of hosts in a cluster that can be ejected. |
 
 
@@ -2406,7 +2436,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | Timeout is the timeout per retry attempt. |
+| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | Timeout is the timeout per retry attempt. |
 | `backOff` | _[BackOffPolicy](#backoffpolicy)_ |  false  | Backoff is the backoff policy to be applied per retry attempt. gateway uses a fully jittered exponential<br />back-off algorithm for retries. For additional details,<br />see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-max-retries |
 
 
@@ -2742,7 +2772,7 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `backend` | _[RateLimitDatabaseBackend](#ratelimitdatabasebackend)_ |  true  | Backend holds the configuration associated with the<br />database backend used by the rate limit service to store<br />state associated with global ratelimiting. |
-| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | Timeout specifies the timeout period for the proxy to access the ratelimit server<br />If not set, timeout is 20ms. |
+| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | Timeout specifies the timeout period for the proxy to access the ratelimit server<br />If not set, timeout is 20ms. |
 | `failClosed` | _boolean_ |  true  | FailClosed is a switch used to control the flow of traffic<br />when the response from the ratelimit server cannot be obtained.<br />If FailClosed is false, let the traffic pass,<br />otherwise, don't let the traffic pass and return 500.<br />If not set, FailClosed is False. |
 | `telemetry` | _[RateLimitTelemetry](#ratelimittelemetry)_ |  false  | Telemetry defines telemetry configuration for RateLimit. |
 
@@ -3100,8 +3130,9 @@ _Appears in:_
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`SecurityPolicy`
-| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `spec` | _[SecurityPolicySpec](#securitypolicyspec)_ |  true  | Spec defines the desired state of SecurityPolicy. |
+| `status` | _[PolicyStatus](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyStatus)_ |  true  | Status defines the current status of SecurityPolicy. |
 
 
 #### SecurityPolicyList
@@ -3116,7 +3147,7 @@ SecurityPolicyList contains a list of SecurityPolicy resources.
 | ---   | ---  | ---      | ---         |
 | `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1`
 | `kind` | _string_ | |`SecurityPolicyList`
-| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
+| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#listmeta-v1-meta)_ |  true  | Refer to Kubernetes API documentation for fields of `metadata`. |
 | `items` | _[SecurityPolicy](#securitypolicy) array_ |  true  |  |
 
 
@@ -3183,8 +3214,8 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds.<br />If unspecified, defaults to 600 seconds. |
-| `minDrainDuration` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  false  | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.<br />If unspecified, defaults to 5 seconds. |
+| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds.<br />If unspecified, defaults to 600 seconds. |
+| `minDrainDuration` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  false  | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.<br />If unspecified, defaults to 5 seconds. |
 
 
 #### ShutdownManager
@@ -3212,7 +3243,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `window` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ |  true  | Window defines the duration of the warm up period for newly added host.<br />During slow start window, traffic sent to the newly added hosts will gradually increase.<br />Currently only supports linear growth of traffic. For additional details,<br />see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig |
+| `window` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | Window defines the duration of the warm up period for newly added host.<br />During slow start window, traffic sent to the newly added hosts will gradually increase.<br />Currently only supports linear growth of traffic. For additional details,<br />see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig |
 
 
 
@@ -3293,7 +3324,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `idleTimeout` | _[Duration](#duration)_ |  false  | IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no<br />bytes sent or received on either the upstream or downstream connection.<br />Default: 1 hour. |
+| `idleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no<br />bytes sent or received on either the upstream or downstream connection.<br />Default: 1 hour. |
 
 
 #### TCPKeepalive
@@ -3309,8 +3340,8 @@ _Appears in:_
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
 | `probes` | _integer_ |  false  | The total number of unacknowledged probes to send before deciding<br />the connection is dead.<br />Defaults to 9. |
-| `idleTime` | _[Duration](#duration)_ |  false  | The duration a connection needs to be idle before keep-alive<br />probes start being sent.<br />The duration format is<br />Defaults to `7200s`. |
-| `interval` | _[Duration](#duration)_ |  false  | The duration between keep-alive probes.<br />Defaults to `75s`. |
+| `idleTime` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | The duration a connection needs to be idle before keep-alive<br />probes start being sent.<br />The duration format is<br />Defaults to `7200s`. |
+| `interval` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | The duration between keep-alive probes.<br />Defaults to `75s`. |
 
 
 #### TCPTimeout
@@ -3324,7 +3355,7 @@ _Appears in:_
 
 | Field | Type | Required | Description |
 | ---   | ---  | ---      | ---         |
-| `connectTimeout` | _[Duration](#duration)_ |  false  | The timeout for network connection establishment, including TCP and TLS handshakes.<br />Default: 10 seconds. |
+| `connectTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ |  false  | The timeout for network connection establishment, including TCP and TLS handshakes.<br />Default: 10 seconds. |
 
 
 #### TLSSettings
@@ -3472,7 +3503,7 @@ _Appears in:_
 | `name` | _string_ |  true  | Name is a unique name for this Wasm extension. It is used to identify the<br />Wasm extension if multiple extensions are handled by the same vm_id and root_id.<br />It's also used for logging/debugging. |
 | `rootID` | _string_ |  true  | RootID is a unique ID for a set of extensions in a VM which will share a<br />RootContext and Contexts if applicable (e.g., an Wasm HttpFilter and an Wasm AccessLog).<br />If left blank, all extensions with a blank root_id with the same vm_id will share Context(s).<br />RootID must match the root_id parameter used to register the Context in the Wasm code. |
 | `code` | _[WasmCodeSource](#wasmcodesource)_ |  true  | Code is the wasm code for the extension. |
-| `config` | _[JSON](#json)_ |  false  | Config is the configuration for the Wasm extension.<br />This configuration will be passed as a JSON string to the Wasm extension. |
+| `config` | _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io)_ |  false  | Config is the configuration for the Wasm extension.<br />This configuration will be passed as a JSON string to the Wasm extension. |
 | `failOpen` | _boolean_ |  false  | FailOpen is a switch used to control the behavior when a fatal error occurs<br />during the initialization or the execution of the Wasm extension.<br />If FailOpen is set to true, the system bypasses the Wasm extension and<br />allows the traffic to pass through. Otherwise, if it is set to false or<br />not set (defaulting to false), the system blocks the traffic and returns<br />an HTTP 5xx error. |