Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.published.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name: durable-workflow-server
# release whose default names another image). Set DW_SERVER_IMAGE to run
# any other native image, by tag or digest; pin a digest for production
# change control.
x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:3.9.1}
x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:3.9.2}

services:
server:
Expand Down
81 changes: 81 additions & 0 deletions docs/releases/3.9.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# 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](https://github.com/durable-workflow/server/releases/tag/3.9.1#upgrade),
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](https://github.com/durable-workflow/server/issues/934)
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](../../resources/platform-protocol-specs/command-key-legacy-v1-vectors.json)
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](https://github.com/durable-workflow/server/pull/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](https://github.com/durable-workflow/server/issues/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](https://github.com/durable-workflow/.github/issues/228); installed
command-key cohorts remain under
[shared #216](https://github.com/durable-workflow/.github/issues/216).

The independent #1194 20-execution gate is complete. The MariaDB re-registration
pool-timeout investigation [#1204](https://github.com/durable-workflow/server/issues/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.
Loading