From 88879edd8eed01472ba56fe53ae6c565a8cb705d Mon Sep 17 00:00:00 2001 From: Luke Knepper Date: Wed, 9 Sep 2026 16:26:57 -0700 Subject: [PATCH 1/2] Clarify Temporal Proxy fail-closed encryption --- .../temporal-proxy/encrypt-payloads.mdx | 25 +++++++++++++++++-- .../temporal-proxy/index.mdx | 6 +++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx b/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx index 418c66b92c..f31efe0718 100644 --- a/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx +++ b/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx @@ -20,8 +20,9 @@ import { ReleaseNoteHeader } from '@site/src/components'; The proxy can encrypt Workflow and Activity payloads on the hop to an upstream and decrypt them on responses, set under the top-level `encryption` block. It is off by default. Workers and Clients keep exchanging cleartext with the gateway; -the proxy seals payloads before they leave and opens them on the way back, so the upstream Temporal Service only ever -stores ciphertext. Encryption is transparent, requiring no change to Worker or Client code. +the proxy seals codec-capable Payloads before they leave and opens them on the way back. New Payloads sent through the +proxy reach the upstream Temporal Service as ciphertext. Encryption is transparent, requiring no change to Worker or +Client code. It uses envelope encryption: a short-lived data encryption key (DEK) encrypts each payload with AES-256-GCM, and a KMS key you own wraps the DEK. The wrapped DEK and a reference to the key that wrapped it travel with the payload, so the @@ -77,6 +78,26 @@ encryption: - `cacheSize` bounds the in-memory cache of decrypted DEKs, which avoids a KMS call on every message. It must be non-negative. +:::note Scope of fail-closed behavior + +Fail-closed applies to outbound codec-capable Payloads on calls that pass through a proxy where `encryption.enabled` is +`true`. If the proxy cannot encrypt one of these Payloads, such as when the KMS is unavailable, it fails the request +before sending it upstream. It does not fall back to plaintext. + +The proxy cannot enforce encryption for a Client, Worker, Web UI, or CLI that connects directly to the upstream Temporal +Service. Restrict credentials and network paths when all application traffic must pass through the proxy. + +On responses, the proxy decrypts Payloads that carry its encryption metadata. It passes other Payloads through unchanged +so data written before proxy adoption remains readable during a migration. This behavior continues until existing +plaintext data ages out under the Namespace's retention period. + +Fail-closed does not mean that every request field is encrypted. Search Attributes remain unencrypted so the Temporal +Service can index them. Failure messages and call stacks are not codec-capable Payloads by default. See +[Codecs and Encryption](/production-deployment/data-encryption) for encryption coverage and +[Failure Converter](/failure-converter) for failure encoding. + +::: + `default` and each `overrides` entry are key policies with the same shape: | Field | Meaning | diff --git a/docs/production-deployment/temporal-proxy/index.mdx b/docs/production-deployment/temporal-proxy/index.mdx index 0377cd00c3..b4c2c79b44 100644 --- a/docs/production-deployment/temporal-proxy/index.mdx +++ b/docs/production-deployment/temporal-proxy/index.mdx @@ -78,8 +78,10 @@ For each request, the gateway: The per-upstream proxy then rewrites the local Namespace to the name the upstream expects, attaches that upstream's TLS and credentials, forwards to the Temporal Service, and translates the Namespace back on responses. When payload -encryption is enabled, it also seals payloads on the way out and opens them on the way back, so the upstream only ever -stores ciphertext. +encryption is enabled, it also seals codec-capable Payloads on the way out and opens them on the way back. New Payloads +sent through the proxy reach the upstream as ciphertext. See +[Encrypt payloads](/production-deployment/temporal-proxy/encrypt-payloads) for the scope and limits of this fail-closed +behavior. ### Terms From cfa7d2ab520aeef7ae9025e250cd5e997d7de242 Mon Sep 17 00:00:00 2001 From: Duncan Mackenzie Date: Thu, 10 Sep 2026 09:43:00 -0700 Subject: [PATCH 2/2] Narrow encryption diagram arrows to Payloads only Codex flagged that the ciphertext/ciphertext-response arrow labels in the fail-closed diagram still imply the whole request and response are encrypted, contradicting the note that Search Attributes and default failure fields stay unencrypted. --- .../production-deployment/temporal-proxy/encrypt-payloads.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx b/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx index f31efe0718..ae6a596ec8 100644 --- a/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx +++ b/docs/production-deployment/temporal-proxy/encrypt-payloads.mdx @@ -46,8 +46,8 @@ flowchart LR App -->|cleartext request| Seal Seal -->|wrap DEK| KMS - Seal -->|ciphertext| Upstream - Upstream -->|ciphertext response| Open + Seal -->|Payloads: ciphertext
other fields: cleartext| Upstream + Upstream -->|Payloads: ciphertext
other fields: cleartext| Open KMS -->|unwrap DEK| Open Open -->|cleartext response| App ```