Repository navigation
Description
Delivered in Native 3.3.0 and PHP SDK 3.11.0
General reconciled the original acceptance against maintained backend controls and the exact published producer/consumer tuple. Acceptance, publication and scope limits. No benchmark speedup or installed SQL-count measurement is claimed. Earlier NONPASSs remain attributed.
Original requirement and historical evidence
External performance report, topic 10a. The reported timings and proposed fixes have not been independently reproduced. The supplied patches are reference drafts for review and current-source qualification.
Problem
An activity completion makes its workflow task ready. The worker's next
workflow poll then claims it, in another locked transaction.
Proposed contract
POST /api/worker/activity-tasks/{task_id}/completeaccepts an optional
workflow_pollobject. It holds a workflow poll request for task kind
workflowonly, under the same rules as
POST /api/worker/workflow-tasks/poll.- The completion's transaction claims a ready workflow task for that
poll_request_id, in a savepoint. - The response carries
workflow_poll: {"leased": true|false}. - The poll under that request ID replays the lease without the lock, when
the replay would write nothing. - Advertised as
activity_completion_workflow_poll.
Reported benchmark evidence
Reporter-supplied cumulative measurements, not an isolated-effect or independently verified performance claim: 200 sequentially started workflows, five sequential 20ms activities or five local activities each, six PHP worker processes, mean of three repetitions, one machine, fresh SQLite/MySQL8.0/PostgreSQL16 databases with default durability. "Five" and "local" below mean last-close wall time in seconds; S/M/P means SQLite/MySQL/PostgreSQL. Preserve regressions and noise in the reported results.
| five | local | |
|---|---|---|
| slowest backend | 19.16 → 17.56 | 4.87 → 4.95 |
Acceptance
- With a carried poll, the woken workflow task is leased in the
completion's transaction, and the replayed poll answers it. - A refused poll leaves the completion recorded.
- Requests without
workflow_pollbehave as before. worker-protocol-api.openapi.yamldocuments the capability and both
fields. The reference commit doesn't yet.
Implementation constraints
Workers should carry the poll only when they can take a
workflow task.
Dependencies
No new producer dependency is required for source investigation.
Related existing work: #325.
Draft patches and validation boundary
Current main was independently read as b8f4dd13623ce645de77ba5bd89ae8dd8eea2f7c. The supplied draft series targets 3d4d4afaf2b24aaa5443eac154e253b011924738; patches are cumulative reference material, not a current-main application or test result. Review and rebase on maintained source, preserve all existing tests and published compatibility, then establish causal controls and actual conformance before shipping. No patch was applied or executed during intake.
Known draft gap / required control: The draft does not yet include the complete versioned OpenAPI/capability update. A carried-poll refusal must not roll back a successfully recorded activity completion.
The following sanitized unified diffs identify proposed reference material:
0011-t10-Carry-the-next-workflow-poll-on-the-activity-complet.patch— 13,995 bytes, SHA-256db7c915cd8bb2df185db3a7f03fc983f8748fb9420999f8d5d3c36673fbda92d.
Current implementation: PR1073 is normally merged as 54af464004d85759e16e939124059449c8052758 / tree 784e5506945c4a6f2072d5005e806e8d8d68f4dd. Its accepted source has62 successful PR checks/one declared skip and48 successful merge-group jobs, with OpenAPI revision63 and the shared carried-poll vectors. The accepted SDK329 source handoff replaces the withdrawn b631 handoff. The automatic main attempts remain NONPASS/runner-blocked after two locked-archive HTTP504 setup failures; this is not a product assertion or published result. No further same-head retry is selected. Next owner/action: Server continues the ordered P0 source train, then owns the coherent published producer and consumer/runner qualification tuple; SDK-PHP owns its accepted consumer source. This issue remains open for published-artifact acceptance. The reported benchmark measurements remain unverified.
Activity
rmcdaniel commentedon Nov 6, 2026
Sanitized reference diff
0011-t10-Carry-the-next-workflow-poll-on-the-activity-complet.patch, part 1/1.This is an unverified, cumulative draft from the external report. Mail author/date/commit-message metadata was removed; the unified-diff hunks were retained. No patch was applied or executed, and no build/test or compatibility result is implied. The known gaps and acceptance criteria in this issue remain mandatory.
Complete sanitized patch: 13,995 bytes, SHA-256
db7c915cd8bb2df185db3a7f03fc983f8748fb9420999f8d5d3c36673fbda92d. This part: 13,995 bytes, SHA-256db7c915cd8bb2df185db3a7f03fc983f8748fb9420999f8d5d3c36673fbda92d. Parts concatenate in order; a part boundary is between complete file diffs.rmcdaniel commentedon Nov 6, 2026
Security static review found two blocking controls missing from the reference implementation.
The activity completion proves ownership with
body.lease_owner, butadmit_carried_workflow_pollindependently trustsworkflow_poll.worker_id. Worker credentials are tenant/role scoped rather than cryptographically bound to one worker ID. Worker A can therefore complete its activity while causing the same transaction to lease a workflow task and cache a replay answer for registered worker B. Requireworkflow_poll.worker_id == completion.lease_ownerbefore admission and revalidate it inside the transaction with the task/fence. Add a cross-worker refusal control proving no foreign lease, binding, or result-cache row is written.claim_carried_workflowcatches everyErrfromclaim_in, rolls back the savepoint, and returnsOk(None). That includes unexpected backend, decoding, stored-shape, budget, and invariant failures, not only the documented soft refusals. An internal fault must not be reported as a successful completion with the carried poll silently omitted. Downgrade only an explicit, closed refusal class; propagate or explicitly surface unexpected failures. Add causal database-error and malformed-stored-state controls while preserving the contract that a normal poll refusal does not erase an already valid completion.This is a static finding only. The supplied patch was not applied or executed.
rmcdaniel commentedon Nov 6, 2026
Sanitized rebased reference for report topic 10a:
0011-t10-Carry-the-next-workflow-poll-on-the-activity-complet.patch.The supplied revision targets Server
b8f4dd13623ce645de77ba5bd89ae8dd8eea2f7c. It is cumulative external reference material, not independently qualified against today's maintained source. Mail headers and commit-message/application instructions were removed; the unified diff is retained. The reporter now claims every rebased commit builds and the tip passes SQLite/MySQL/PostgreSQL tests. Those are attributed claims, not a new maintainer test result. Existing acceptance criteria, security findings and completed implementation receipts remain authoritative. Earlier attached patches are retained as historical references.Sanitized patch: 14,027 bytes, SHA-256
7d671325c50584b126ead2038390419748362d70a2709648da97d3543d98b6a3. Original-base sanitized identity:db7c915cd8bb2df185db3a7f03fc983f8748fb9420999f8d5d3c36673fbda92d. No patch was applied or executed during this update.rmcdaniel commentedon Nov 6, 2026
Security follow-up on the updated rebased reference
0011-t10-Carry-the-next-workflow-poll-on-the-activity-complet.patch(14,027 B / SHA-2567d671325c50584b126ead2038390419748362d70a2709648da97d3543d98b6a3): both blockers in 6692716653 remain.The rebase updates surrounding maintained capability context, but
admit_carried_workflow_pollstill trustsworkflow_poll.worker_idindependently of the completed activity'slease_owner; no equality is revalidated with the task/fence inside the transaction.claim_carried_workflowalso still catches everyErr(_)fromclaim_inand returnsOk(None), so unexpected database, decoding, stored-state, budget and invariant faults can still masquerade as a successful completion with an omitted carried result.The updated reference therefore still needs the cross-worker no-lease/no-binding/no-cache control and a closed documented soft-refusal class with unexpected faults propagated or explicitly surfaced. Static review only; no patch was applied or executed.
rmcdaniel commentedon Nov 7, 2026
Accepted producer checkpoint: PR1073, accepted head
511bd6fd, normally merged54af4640. Its contract is included in the accepted 4fb runtime and now the immutable published native 3.2.0 source/tag3c6f1eda9c6d2ebc0ee5bec8ccf431900052be9e. The earlier reference-draft same-worker/error findings are superseded by that implementation and its actual SQLite/PostgreSQL/MySQL/MariaDB Source controls. They are not remaining implementation holds on the accepted producer.The authoritative OpenAPI schema 63 and closed replay vectors retain protocol 1.20. Schema SHA-256 is
d6c726a7f97417494d9897ae1101ac7300ba6414174041dea875ae01e5052391; vectors SHA-25612ca5db29d96b5e0f03852b698ca1d15bd796c07486a1af85484d4e4dfc45e9b.Capability
activity_completion_workflow_polladmits the optionalworkflow_pollon activity completion, under that completion's owner and retained registration fence. A live activity slot with known or unknown expiry declines the opposite-kind claim. Malformed/unsupported admission and the closed soft-refusal table are separate from unexpected internal/backend errors, which remain visible and cannot masquerade as an empty claim. Duplicate and uncertain completion recovery retains original completion and poll identities.The actual publisher input is now available: owner terminal PASS, independent Security publication PASS, index
ghcr.io/durable-workflow/server@sha256:6916f6f3bb1ee58d071f10f888068fd321cd1576fb70dc97ce8e9e61da493d62, exact producer/native runner 3c6. This issue stays open for actual published qualification. Server next owns the existing corpus/four-cell Compose receipt packet 325/6705614909. General next binds the actual published SDK package and SDK runner plus the bounded invocation to this producer; SDK-PHP owns its existing consumer/harness execution and result. The shared consumer handoff is SDK293/6705418888. Installed clock/transit/buffer-age, missing-key capacity, lost-answer/original-ID recovery, expiry/refence and selected load acceptance remain open. No tentative/withdrawn head, Source fixture or older tuple supplies that result.rmcdaniel commentedon Nov 9, 2026
General reconciled the carried-poll and workflow-clock delivery against the original acceptance criteria while both repository agents are Off.
The producer is published Native Server 3.3.0, source
2a15179f29801eec9f2a2d4e6a9c5f93233f104e, indexsha256:cb4b11bd6235a551cf51e7dc6342504fbbcef19959618b376fb5648ca00fc388. The consumer is normal published PHP SDK 3.11.0, sourcefbc64ef98c27be467d75a29a29bfb0ee4e80dba7.Feature-specific acceptance is covered by the maintained source controls. The carried-poll runtime tests, HTTP execution tests, workflow replay/history-budget tests and versioned OpenAPI are byte-identical between the qualified integrated source
5f937ec8(run 42448138571) and the 3.3.0 cut. The source lanes execute the registered controls on SQLite, MySQL, MariaDB and PostgreSQL; the accepted #1073 source also has 62 successful checks and its declared skip.Published compatibility is now verified with the unchanged full PHP replay matrix: 42531701411, 13 executed scenarios passed, zero skips, exact Server 3.3.0 and normal Packagist SDK 3.11.0, distinct clients, restarted worker, completed-history replay/query, in-flight signal/restart and nondeterminism refusal. Captured audit. Its runner bootstrap fix has complete ordinary main custody: signed reviewed tree, 71 successful main checks/eight expected skips and topic absence verified. The published product bytes and feature-specific controls are unchanged.
The source controls establish the transaction/receipt/answer invariants. The published matrix establishes producer/consumer compatibility; it is not an installed SQL-count or benchmark experiment. No speedup is claimed. #1073's earlier archive-acquisition NONPASSs and the first published replay's interpreter-bootstrap NONPASS remain attributed.
Acceptance:
qualify_carried_workflow_pollschecks the completion's workflow claim and the same receipt/task/attempt/history/ready-age on ordinary replay without another transition. Refused carriers preserve a valid recorded completion and the ready task. The optional field, capability and response are documented. Published SDK 3.11.0 contains the accepted #329 consumer.The separate condition-wait durable-workflow/sdk-php#269 final-audit C2/C5 follow-up remains open; it is not a carried-poll or workflow-clock acceptance claim. The original reporter benchmark remains unverified.