Skip to content

Adopt Core 2.14.2 and make PHP stream and payload writes atomic - #791

Merged
rmcdaniel merged 17 commits into
mainfrom
fix/php-handoffs-784-787-789
Oct 26, 2026
Merged

rmcdaniel merged 17 commits into
mainfrom
fix/php-handoffs-784-787-789

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

PHP Server could deadlock concurrent first stream appends or commit input references after their bytes were deleted. This integrates the three PHP handoffs and the published Core protocol/authority fixes, released in Server 2.11.3.

  • Adopt normally published Workflow 2.14.2 (d60ce5f60e70b834c5d4ef142c3d5dc415cd39fe). Worker completion receives the authenticated protocol and principal through the protocol-aware bridge. Server continues to advertise 1.20; missing capability fails closed, replay ownership stays enforced, and waits remain bounded to 60 seconds.
  • Serialize first stream appends through the existing run lock, discover without a missing-key InnoDB gap lock, then lock found rows by primary key. Creation retains quota admission and stale snapshots reuse the committed stream.
  • Verify opaque input references before the writer, then claim them at its outer commit after ownership locks, in canonical object order. Cleanup-wins rolls back the writer and callbacks. Savepoints have explicit claim lifetimes, and retained schedules protect shared input objects during run pruning.

Validation includes 429 focused cases / 5,123 assertions across SQLite, MySQL 8, MariaDB 10.11 and PostgreSQL 17, with real commit/cleanup races and counterfactual failures against the previous behavior. Targeted final SQL checks and formatting passed. Hosted PHP qualification passed 3,242 tests / 72,224 assertions, corpus, production-image readiness and database TLS; six existing metadata deprecations and intended skips remain reported.

Merged through the protected queue at 8009904aac5d0a2bf082f06ec0f9f35b816d885a. Both required aggregate checks and the genuine Sonar App check passed for that group; all six independent main workflows passed. No queue or main protection was bypassed.

Server 2.11.3 and chart 0.3.3 were published by successful release run 40414327142. Both registries expose the same amd64/arm64 image index, sha256:923a8924ecad13485562d7af30dc87d7fd6d9d7d4758ec8113bac0766fa8603e. Published image checks passed exact source/package identity, trust stores, first-run readiness, source-free Compose, database TLS/certificate refusals and protocol catalog convergence.

Installed SDK/Nexus acceptance is running against that exact digest with published packages in run 40418210934. Those acceptance outcomes remain open. Newly handed-off workflow-binding defects are tracked separately in #794 and durable-workflow/workflow#947. Native schema capture remains with the Rust owner.

Refs #784, #787, #789; durable-workflow/workflow#942.

rmcdaniel and others added 16 commits October 26, 2026 18:10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2.14.1 is 2.14.0 plus the external-worker pending-count limits (Workflow
#933, #939) and its release manifest. It replaces the held 2.14.0 pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workflow 2.14 re-authorizes an admitted service call against its stored
caller scope and current catalog policy, schedules a workflow caller's
handler after its completion commits, and bounds every service-operation
wait at 60 seconds.

- The execute route passes the admitted caller namespace and the request
  principal into the control plane, so the package checks the identity
  the boundary admitted; a package authority refusal is a plain 403.
- The execute route and workflow-task completion validation refuse a
  service-operation wait above 60 seconds with the Server's own message.
- Tests run the scheduled RunServiceCall effects the queue worker would,
  and assert the scheduled admission (ServiceOperationScheduled, no
  synthesized ServiceCallStarted) before them.

Still open: protocol 1.21 and its gate, and the execute route's contract
for callers that name a workflow (scheduled, not inline).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…til the run commits

A failing race test, not a fix. On MySQL, MariaDB, PostgreSQL and SQLite,
run retention deletes an external payload object between a workflow
start's committed claim and the transaction that writes the run, and the
start then commits a run whose arguments reference the deleted object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

rmcdaniel commented Oct 26, 2026 •

Copy link
Copy Markdown
Member Author

Exact PR head 9d7cd8fcba3dda8bcec984e7048d0ffa27566d00, tree 191e7b605a87daa79e88f74ffbd2bc962f3d141c, has completed hosted qualification: 19 success /6 intended skips, no pending or failed checks at enqueue.

PHPUnit Feature40406234737 and its PHP job pass. The complete feature/Nexus/corpus suite ran 3,242 tests /72,224 assertions, with6 existing metadata deprecations and37 skips; test execution took10m20.850s. Release-image contracts, regression-corpus controls, the candidate production image, first-run readiness, all8 container-logging cases and database TLS/certificate refusals pass. Policy, public boundary, replay/query topology, bounded-growth/performance, CodeQL and genuine Sonar qualification also pass. The earlier failed head remains historical evidence.

Enqueued with --match-head-commit on that exact head. The actual combined group is 8009904aac5d0a2bf082f06ec0f9f35b816d885a, position1, created21:57:15UTC. Group PHP qualification40408615926 and the full Shared Server fixture matrix40408615759 are running. The automatic trusted Sonar path remains in force; no manual analysis or bypass is requested.

Next is the protected group result and independent merged-main qualification, followed by PHPServer2.11.3/chart0.3.3 publication and actual installed SDK/Nexus acceptance. The published Nexus workflow's updated artifact pins are prepared on test/php791-installed-acceptance, but have not been run against an unpublished image. #784/#787/#789 and Workflow #942 remain open through artifact acceptance. The newly handed-off #794 is separate work and does not change this qualified candidate.

Completed local fixtures are cleaned up: all3 task-owned SQL containers, their isolated network and3 temporary qualification/counterfactual worktrees are gone. Active source and normally installed dependencies are retained for release follow-through.

Merged via the queue into main with commit 8009904 Oct 26, 2026
26 checks passed
@rmcdaniel

Copy link
Copy Markdown
Member Author

PR #791 merged through the protected queue at 22:21:32UTC as exact qualified group 8009904aac5d0a2bf082f06ec0f9f35b816d885a, tree 1423c7d06b3b1e28106b726952b0e90b89af38c2. Its parents are previously accepted main 65b11820... and PR head 9d7cd8fc...; the combined tree includes #790's native changes as well as this PHP candidate.

The full Shared Server group40408615759, PHP group40408615926, and genuine automatic Sonar App12526 check121879803092 passed. No manual scanner upload or queue bypass was used.

Independent merged-main qualification is also complete: PHPUnit Feature40411811644 succeeded at22:37:46UTC; Sonar40411811234, CodeQL40411810488, replay/query40411811632, performance40411811311 and public boundary40411811070 all succeed. The merged source passed complete PHP/Nexus/corpus qualification, candidate production-image readiness and databaseTLS/certificate refusals.

The source manifest identifies PHPServer2.11.3/chart0.3.3 and locks normally published Core2.14.2. Both exact registry images and the2.11.3 tag were verified absent before starting publication. The protected Release workflow will publish and verify the immutable artifacts. Actual published image identity and installed SDK/Nexus acceptance remain to be recorded; neither a tag push nor a passing source suite is that evidence. #784/#787/#789 and Workflow #942 stay open through their artifact acceptance. #794 remains an explicitly separate repair and is not claimed fixed by this version.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Server 2.11.3 and chart 0.3.3 are published. Release run 40414327142 completed successfully, including both registry publications and immutable chart verification. Source is the protected queue merge 8009904aac5d0a2bf082f06ec0f9f35b816d885a; required group checks, genuine Sonar App and all six independent main workflows passed.

Both durableworkflow/server:2.11.3 and ghcr.io/durable-workflow/server:2.11.3 resolve to the amd64/arm64 index sha256:923a8924ecad13485562d7af30dc87d7fd6d9d7d4758ec8113bac0766fa8603e. Hosted exact-publication verification checked registry equality and source/package labels. Independent GHCR reads confirm both platform configs identify normal locked Workflow 2.14.2 / d60ce5f60e70b834c5d4ef142c3d5dc415cd39fe. Published image checks passed trust stores, first-run setup, source-free Compose, database TLS/certificate refusals and protocol catalog convergence.

Installed Nexus acceptance run 40418210934 is active at acceptance-branch head 09cdc16f7466f2d5c2aae9b31c1c24adbd171589, using the exact published image digest, Core 2.14.2, PHP SDK 3.5.1, Python SDK 2.11.2, CLI 2.3.0 and Waterline 2.13.0. Actual consumer outcomes remain unverified until that execution finishes; this issue stays open for its remaining acceptance scope. New workflow-bound Nexus defects remain separately owned in Server #794 / Workflow #947.

@rmcdaniel

rmcdaniel commented Oct 26, 2026 •

Copy link
Copy Markdown
Member Author

Security triage of the structured GitHub annotations from installed acceptance run 40418210934: this is a genuine acceptance failure, but the current evidence does not show an authorization bypass or security incident.

The passing Python authorization evidence is substantive: the exact probe requires no ServiceCallStarted, exactly one ServiceCallFailed with rejected_forbidden, and the expected typed SDK failure. Its evidence validator additionally requires a single worker-attributed durable/audit row that was never accepted, started, or linked to a target workflow, an administrative HTTP 403, and a 404 when checking the protected namespace name from the caller namespace.

Every administrative refusal in the full matrix returned HTTP 403. The PHP authorization cases nevertheless remained pending until the 30-second caller workflow timeout, so the no-admission/no-dispatch/audit conditions above are unverified for PHP rather than passing or bypassing. Every external-recovery pair failed before the induced kill because the original call and waiting linked service were not observed; recovery acceptance is therefore also unverified. The uncaught-failure cases reached terminal failed/uncaught observations as recorded.

Do not use this run as PHP authorization or recovery acceptance. The bounded raw artifact and runtime logs were not read during this security triage; product diagnosis remains with the owning #791/#794 work. No operator page or release-wide security hold follows from these annotations.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The first exact-published-tuple Nexus acceptance run 40418210934 finished failed. Server 2.11.3 / Core 2.14.2 / PHP SDK 3.5.1 / Python SDK 2.11.2 / CLI 2.3.0 / Waterline 2.13.0 were used; the image was pinned to published index sha256:923a8924ecad13485562d7af30dc87d7fd6d9d7d4758ec8113bac0766fa8603e.

The hosted check annotations establish:

  • All eight uncaught typed-failure caller/service/namespace observations qualify.
  • All four Python-caller authorization observations qualify. Four PHP-caller authorization observations time out waiting for the caller workflow after 30 seconds; the direct admin refusal remains HTTP 403 in every case.
  • All eight external recovery observations fail to observe the original call plus waiting linked service before the kill checkpoint. They do not prove recovery or reference access. A missing WorkflowFailed summary is insufficient to diagnose why.

The acceptance assertions and original budgets remain intact. Diagnostic run 40420956902 repeats the same published tuple at fixture head 1e12cdbc33d4d1ec0a32362088e5b9c8a53b3c8f, adding only bounded last-observed event types and worker diagnostics. The existing 13 evidence-reader checks and PHP/Python syntax checks pass. This distinguishes an obsolete fixture event expectation from an actual delivery defect before changing either behavior or the qualification contract.

Installed consumer acceptance remains open. The package/source lifecycle fixes in Server #794 / Workflow #947 remain unreleased and are not claimed by this published-image result. Release/image/chart publication itself passed; this result does not establish completion of the remaining acceptance work.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security terminal follow-up for diagnostic run 40420956902, exact published tuple Server 2.11.3 / Core 2.14.2 / PHP SDK 3.5.1 / Python SDK 2.11.2 at fixture head 1e12cdbc33d4d1ec0a32362088e5b9c8a53b3c8f: the run completed failed at 23:49:39 UTC. This narrows the earlier triage but does not establish an authorization bypass.

The bounded check annotations show every Python authorization path reaching its expected terminal evidence. Each PHP authorization path instead remained after StartAccepted / WorkflowStarted with the caller pending; its worker diagnostic ended when completeWorkflowTask() received HTTP 409. The PHP external-recovery paths failed before the original call plus waiting linked service became observable; some reached RepairRequested, which is not recovery acceptance.

Released-source review confirms the 409 is fail-closed. Server 2.11.3 validates workflow-task ownership before command processing and again under the task row lock before authorization replay or bridge mutation. PHP SDK 3.5.1 retries only tightly structured 503 storage/backend/lock-pressure outcomes or bounded transient transport failures. A 409 is accepted as lost authority only for exact task-bound run_closed, task_not_leased, or lease_expired envelopes; any other ServerException is rethrown rather than converted into a workflow mutation or failure report.

The annotation retains only the generic HTTP 409 message, not its structured response reason, so the exact product root cause remains unproven. This run must not be used as PHP authorization or external-recovery acceptance. It provides no bypass evidence and creates no security incident or release-wide security hold; installed consumer acceptance remains open under the product owners.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant