Skip to content

0.11.0

Choose a tag to compare

@dg-coreylweathers dg-coreylweathers released this 14 Sep 13:58
· 20 commits to main since this release
db64503

Breaking change

A Flux speech-to-text or Flux text-to-speech wss:// connection behind a TLS-inspecting proxy or private CA that worked on 0.10.1 only because another crate in your dependency graph enabled tokio-tungstenite/rustls-tls-native-roots or native-tls now fails with UntrustedTlsCertificate until you enable rustls-tls-native-roots on deepgram (or pass Deepgram::tls_config). No public signature changed.

Added

  • rustls-tls-native-roots cargo feature: wss:// WebSocket connections also trust the operating system's certificate store, on top of the bundled webpki roots (never instead of them). For TLS-inspecting proxies (Zscaler, Netskope, …), internal CAs, and self-hosted deployments. Named after the tokio-tungstenite and reqwest features it mirrors; rustls-native-certs honors SSL_CERT_FILE / SSL_CERT_DIR in place of the platform store. If the store cannot be loaded (a missing or non-PEM SSL_CERT_FILE, a container with no store), the client continues with the public roots and reports that state explicitly (see TlsTrust below).
  • Deepgram::tls_config(impl Into<Arc<rustls::ClientConfig>>): supply your own rustls configuration once, on the client, and every wss:// WebSocket it opens (live transcription, Flux speech-to-text, Flux text-to-speech) uses it verbatim. rustls is re-exported as deepgram::rustls so the versions match.
  • DeepgramError::UntrustedTlsCertificate { host, trust, source }: returned instead of a bare WsError when the server certificate's issuer is not in the trust roots. The message ends with the remedy that applies to the trust roots actually in effect: enable the feature, install the CA in the OS store, fix an SSL_CERT_FILE whose roots could not be loaded, or adjust the supplied config. Where a hint mentions SSL_CERT_FILE, it asks for a PEM bundle holding the CA together with the public roots you rely on, not the CA alone: once set, the variable replaces the OS store for these WebSockets and, on Linux, for the REST client (reqwest's platform verifier reads the same variables), so a file with only the proxy CA would break REST calls to hosts that CA did not sign.
  • deepgram::tls module with TlsTrust (webpki, webpki_and_native, webpki_native_unavailable, custom), the trust roots in effect for a connection. webpki_native_unavailable means the rustls-tls-native-roots feature is on but no native root could be loaded, so only the bundled roots were checked; the load errors are logged at tracing WARN level.
  • Connect-diagnostics records gain tls_trust (present on every wss:// attempt; absent for plaintext ws://, where no TLS handshake occurs) and tls_resumed (present once the TLS phase completed). Resumed handshakes are cheaper than full ones, so tls_handshake_ms should be compared within one value of tls_resumed. Additive; schema_version stays 1.

Changed

  • BREAKING: A Flux speech-to-text or Flux text-to-speech wss:// connection behind a TLS-inspecting proxy or private CA that worked on 0.10.1 only because another crate in your dependency graph enabled tokio-tungstenite/rustls-tls-native-roots or native-tls now fails with UntrustedTlsCertificate until you enable rustls-tls-native-roots on deepgram (or pass Deepgram::tls_config). No public signature changed. Cause: every wss:// WebSocket surface (live transcription, Flux speech-to-text, Flux text-to-speech) now connects through one explicit rustls connector owned by the Deepgram client, so trust roots and TLS provider are identical across surfaces and no longer depend on which TLS features other crates enable on tokio-tungstenite. Previously only /v1/listen with connect-diagnostics used an explicit connector, and the Flux surfaces took whatever feature unification produced. None of this applies to plaintext ws:// connections (an http:// base URL): they perform no TLS handshake and verify no certificate, so neither the feature nor tls_config affects them; keep http:// to local testing and use https:// whenever credentials or private traffic are involved.
  • The default TLS configuration is built once per Deepgram client (on its first WebSocket connect) and reused, so TLS sessions can be resumed across connections from the same client. Before, a fresh configuration was built per attempt and no session was ever resumed.
  • The TLS dependencies (rustls, tokio-rustls, rustls-pki-types, webpki-roots) are now enabled by the listen and speak features rather than only by connect-diagnostics. They were already present in the dependency graph through tokio-tungstenite; nothing new is downloaded.

Fixed

  • With connect-diagnostics enabled, connections behind a TLS-inspecting proxy failed even where the same application's 0.10.0 build succeeded: the explicit connector introduced in 0.10.1 bypassed the OS-root merge that tokio-tungstenite/rustls-tls-native-roots (enabled elsewhere in the consumer's dependency graph) had been providing through feature unification. Enable rustls-tls-native-roots on deepgram to restore that behavior explicitly.
  • On a client's first connect the OS certificate store (when enabled) is read before any phase timer starts, so it is never charged to tls_handshake_ms. That first connect's connect_duration_ms can therefore exceed the sum of the phase timings by the one-time trust-store load, which is attributed to no phase. A plaintext ws:// client never resolves TLS at all, so it does not read the store (or log about it).
  • {:?} on a Deepgram client (or on a sub-client holding one, such as Transcription or Speak) printed the API key or temporary token: reqwest::Client's Debug output includes its default headers, and the Authorization header value was not marked sensitive. It now is, so the header prints as Sensitive.

Full changelog: 0.10.1...0.11.0