Skip to content

3.9.2

Choose a tag to compare

@github-actions github-actions released this 13 Nov 16:22
· 59 commits to main since this release
Immutable release. Only release title and notes can be modified.
5614274

Durable Workflow Server 3.9.2.

Git tag 3.9.2 → 5614274d2629d03f92932a07dfee0fb10349ddd9
Image index sha256:8ffcdb2a36af3129a1987849aafe8715fe0d3bf9a9648467f0b5cb8eeef43ba9 in durableworkflow/server and ghcr.io/durable-workflow/server
Release run https://github.com/durable-workflow/server/actions/runs/43452744563

Durable Workflow Server 3.9.2 (native)

Server 3.9.2 corrects Unicode signal/update command keys and makes keyed
admission receipts explicit. It also hardens the owner check on storage-admission
observation files. Its immutable images are durableworkflow/server:3.9.2 and
ghcr.io/durable-workflow/server:3.9.2; the published Compose default selects
3.9.2. Rolling aliases move separately after published-image qualification.

Upgrade and rollback

From 3.9.0 or 3.9.1, no schema step is needed. Stop Server replicas, back up
the database and external-payload storage, select the new image, restart and
verify readiness, reported version and worker registration. The physical schema
and existing command/intent rows are unchanged.

Upgrades from 3.8.x or earlier still require the explicit 3.9 schema upgrade:
SQLite 12 → 13, PostgreSQL and MariaDB 13 → 14, and MySQL 14 → 15. Follow the
3.9.1 upgrade procedure,
using the 3.9.2 image for schema-upgrade and every restarted replica. Older
steps are applied where needed. Rollback to 3.8.x requires restoring the backup.

A rollback to 3.9.1 uses the same schema but restores the Unicode-key and receipt
metadata defects described below and removes the observation-owner hardening.
The worker protocol remains 1.20 and the control plane remains version 2.

Command keys and receipts

Installed CLI and SDK controls
found that 3.9.1 accepted a 255-character multibyte request_id at the HTTP
boundary but then refused it with 422 invalid_request_id at the store's
255-byte check. The store now applies the existing 255 Unicode code-point
limit. A 255-character key made of two-byte or four-byte characters is accepted;
256 characters are refused without admission. Existing normalization, byte-exact
identity and hashed storage remain unchanged. The body request_id is the
command key; the HTTP X-Request-Id header is not a retry key.

Fresh keyed signal and accepted update receipts now echo the literal
request_id and report retained:false, intent_verified:true. A retained
receipt echoes that key with retained:true and preserves its original command,
run and update identities. A modern intent proof reports intent_verified:true;
a compatible pre-intent legacy readback reports intent_verified:false, without
fabricating equality. Unkeyed and bridge receipts keep their existing behavior.

The same-key intent/conflict, close/continue lookup and zero-write authority
boundaries from 3.9.1 remain. A raw/token or collation-only identity ambiguity
still fails closed as 409 request_id_ambiguous, retryable:false, with no
selected receipt or writes. A retained update does not claim a retry's external
payload reference. The accepted
legacy-key vectors and upgrade procedure
separate synthetic legacy shapes, physical upgrades and committed-response loss.
Source tests do not establish the installed client cohorts under shared #216.

Storage-admission observation ownership

When storage admission is enabled, the already-opened observation descriptor
must belong to root or the effective Server UID. A foreign owner fails closed
through the existing unavailable/fenced admission outcome. The check uses the
same descriptor as the bounded type/mode/content read, avoiding a separate path
lookup (#1206).

Operators must still provide trusted ancestors and the intended read-only
container mapping. The runtime does not enforce ancestor ownership. Cloud's
physical collector, UID/mount mapping and adoption acceptance remain separate.
Draining completion-upload allowances are not added by this patch; see
#951.

Retained limits and qualification

The 3.9.1 encoded completion budget, discovery field and bounded 64 MiB/two-second
refusal delivery remain unchanged. This patch grants no new external-payload or
continuation-command authority. Installed PHP/Python/Rust Worker completion
qualification is recorded separately under
shared #228; installed
command-key cohorts remain under
shared #216.

The independent #1194 20-execution gate is complete. The MariaDB re-registration
pool-timeout investigation #1204
remains open and is not fixed here. Pending, aborted and infrastructure-blocked
checks are not counted as qualification passes. This release does not enable
Cloud native adoption or publish the later dispatch-summary schema feature.