Is your feature request related to a problem?
temporalio_client::TlsOptions accepts TLS material as PEM byte strings only:
pub struct TlsOptions {
pub server_root_ca_cert: Option<Vec<u8>>,
pub client_cert: Option<Vec<u8>>,
pub client_private_key: Option<Vec<u8>>,
// ...
}
This works when certificates are static files, but it can't represent a rustls::ClientConfig built with a custom ResolvesClientCert or ServerCertVerifier, which is the standard rustls pattern for:
- Short-lived certificates with dynamic in-process rotation
- Custom server-certificate verification (pinning, SAN-URI trust-domain extraction, federated roots)
- TLS configuration owned by another crate that already manages the rustls setup
In these cases the caller already holds an Arc<rustls::ClientConfig> whose embedded resolver/verifier re-reads the cert source on every handshake. Re-serializing that to PEM bytes produces a one-time snapshot: rotation breaks, custom verification is lost.
Describe the solution you'd like
Allow passing an Arc<rustls::ClientConfig> directly, bypassing PEM parsing. For example:
pub enum ClientTlsConfig {
/// Existing path: PEM bytes parsed into a rustls config internally.
Pem(TlsOptions),
/// New: caller-supplied rustls config used as-is.
Rustls(Arc<rustls::ClientConfig>),
}
Or equivalently, an additional field on the existing options struct that takes precedence when set.
tonic::transport::ClientTlsConfig already exposes .rustls_client_config(Arc<ClientConfig>), so the plumbing through to the underlying channel should be minimal; the request is to expose that path through temporalio_client's public surface.
Describe alternatives you've considered
- Extract PEM bytes from the issued config and pass those. Works for the initial certificate's lifetime, but the connection holds the snapshot. When the source rotates, the worker keeps presenting the stale cert until process restart.
- Reconnect on a timer. Possible but ugly: requires guessing rotation cadence, drops in-flight long-polls, and still can't represent a custom verifier.
- Fork/patch the client crate. Unblocks, but maintenance burden.
Additional context
The ClientConfig in question is itself stable for the process lifetime; the dynamism lives inside the ResolvesClientCert / ServerCertVerifier it was built with. So a one-time Arc<rustls::ClientConfig> hand-off is sufficient: there's no need for a "reloadable" hook on the temporalio_client side, just pass-through of the config as-is.
Is your feature request related to a problem?
temporalio_client::TlsOptionsaccepts TLS material as PEM byte strings only:This works when certificates are static files, but it can't represent a
rustls::ClientConfigbuilt with a customResolvesClientCertorServerCertVerifier, which is the standard rustls pattern for:In these cases the caller already holds an
Arc<rustls::ClientConfig>whose embedded resolver/verifier re-reads the cert source on every handshake. Re-serializing that to PEM bytes produces a one-time snapshot: rotation breaks, custom verification is lost.Describe the solution you'd like
Allow passing an
Arc<rustls::ClientConfig>directly, bypassing PEM parsing. For example:Or equivalently, an additional field on the existing options struct that takes precedence when set.
tonic::transport::ClientTlsConfigalready exposes.rustls_client_config(Arc<ClientConfig>), so the plumbing through to the underlying channel should be minimal; the request is to expose that path throughtemporalio_client's public surface.Describe alternatives you've considered
Additional context
The
ClientConfigin question is itself stable for the process lifetime; the dynamism lives inside theResolvesClientCert/ServerCertVerifierit was built with. So a one-timeArc<rustls::ClientConfig>hand-off is sufficient: there's no need for a "reloadable" hook on thetemporalio_clientside, just pass-through of the config as-is.