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.5.0}
x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:3.6.0}

services:
server:
Expand Down
87 changes: 87 additions & 0 deletions docs/releases/3.6.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Durable Workflow Server 3.6.0 (native)

Server 3.6.0 lets clients read an update's outcome later, gives workflow tasks
a replay-safe entry clock, resumes retried activities from their last
heartbeat, and scans every published image for fixable vulnerabilities. Its
exact images are `durableworkflow/server:3.6.0` and
`ghcr.io/durable-workflow/server:3.6.0`; the published Compose default selects
3.6.0. Rolling aliases move separately after published-image qualification.

## Upgrade

**No schema upgrade.** The native schema stays at 12 on MySQL, MariaDB and
PostgreSQL and at 11 on SQLite, so a 3.5.0 database runs on 3.6.0 as it is.
Replace the image and restart. Databases still on 3.4.x or earlier need the
[3.5.0 schema upgrade](3.5.0.md#upgrade) first.

Rolling back to 3.5.0 is an image change. The worker protocol stays at `1.20`
and the control plane at version `2`.

## Read an update's outcome later

`GET /api/workflows/{workflow_id}/updates/{update_id}` returns an accepted
update's receipt without admitting another update
([#1131](https://github.com/durable-workflow/server/issues/1131)). It answers
like submission: 202 with `update_status: accepted` while the handler runs
(never a null result), 200 when it completed (an encoded null result
included), 422 when it failed. With `wait_for=completed` and
`wait_timeout_seconds` it waits for the outcome. A missing or pruned update is
404 `update_not_found`, which does not prove the update was never admitted.
Cluster info advertises `update_outcome_reads: true`. See
[Update outcome reads](../contracts/update-outcome-reads.md).

## Replay-safe entry clock on workflow tasks

Each workflow task carries `replay_clock`, the instant the run's replay starts
from, so an SDK's replay-safe clock has a value at ordinary workflow entry
([#1132](https://github.com/durable-workflow/server/issues/1132)). Ordinary,
continued and child runs use their own start. A redriven run uses its source's
replay anchor, only when the redrive command and link agree; otherwise the
object is omitted. See
[Worker replay entry clock](../contracts/worker-replay-entry-clock.md).

## Activity retries resume from the last heartbeat

A worker that lists `activity_heartbeat_resume` receives
`last_heartbeat_details` and `last_heartbeat_at` on a retry attempt's claim:
the latest acknowledged heartbeat from earlier attempts of the same activity
([#1139](https://github.com/durable-workflow/server/issues/1139)). Native
advertises `activity_heartbeat_resume: {supported: true, version: 1}` in
worker `server_capabilities`.

## Vulnerability scan of published images

Each release now scans both published architecture images with a pinned
Trivy and keeps a compact receipt. A HIGH or CRITICAL finding with a fixed
version fails the release run, which holds alias promotion. `latest` is
rescanned weekly ([#802](https://github.com/durable-workflow/server/issues/802)).

The first scan found CVE-2026-109518 (HIGH) in `apt` and `libapt-pkg6.0`
2.6.1 in the 3.5.0 runtime base. 3.6.0 moves the base to the current Debian
12 bookworm-slim image, which has 2.6.2. The server never runs apt. Security
recorded the remaining unfixed Debian rows as accepted residual risk on #802.

## Other changes

- A workflow-task completion that carries commands may be up to 16 times the
per-payload limit (32 MiB by default), so large fan-outs complete. A larger
one is refused with 413 `payload_too_large` and
`limit_kind: workflow_task_completion_bytes`. Each command's arguments still
meet the per-payload limit
([#1136](https://github.com/durable-workflow/server/issues/1136)).
- Re-applying an unchanged schedule is a no-op: it records no event and keeps
`next_fire_at` and its jitter. Only a `spec` or `jitter_seconds` change
moves the next fire, and `ScheduleUpdated.changed_fields` lists only fields
that changed, as Workflow 2.24.0 does
([#1147](https://github.com/durable-workflow/server/issues/1147)).
- Operator metrics report `runs.replay_blocked`, `oldest_replay_blocked_at`
and `max_replay_blocked_age_ms`, and health has an advisory
`replay_blocked_runs` check that warns while any open run cannot replay
([#1154](https://github.com/durable-workflow/server/issues/1154)).

## Known limitations

The [3.3.0 known limitations](3.3.0.md#known-limitations) still apply.
On MySQL, `json` columns can still round doubles
([#1016](https://github.com/durable-workflow/server/issues/1016)); that fix is
planned for 3.7.0 with a MySQL-only schema upgrade.
Loading