Skip to content

Nexus workflow-bound service handlers are unusable for SDK-worker workflows in 2.11.1 #794

Open

Description

@rmcdaniel

Operator decision, November 1: no more PHP Server releases. Published Server 2.11.8 / Core 2.15.12 is the final PHP Server tuple. PR #924 is closed without merge/publication, auto-merge disabled, and unpublished 2.11.9 / chart 0.3.9 metadata withdrawn. Published 2.11.8 retains the known deadline-acknowledgment defect. Native #926 owns the corrected Server contract. General continues Rust SDK #146, related documentation and exact installed consumer acceptance against qualified native artifacts. Source-only PHP candidate evidence is retained as historical evidence and does not establish native acceptance.

Current state, November1 2026: Published PHP Server2.11.8 / Core2.15.12 is available: Server source fa3fc2f2f6b8935ea4a6eea47f6a9221e2adafff, Core source 7c80ffccdb6ab6e6ace8339618a9d6f1d6d9432f, immutable image index sha256:3848d5d5cd1b23bd2881e3fdecea64cc44b72e6fb812e577c2db6d0872d065dd. The normal publisher and matching chart0.3.8 verification pass. Exact installed Server/Core file and package-provenance identity has been verified; that identity proof does not establish all Nexus behavior.

The published PHP/Python Nexus run passes all 14 aggregate scenarios, 28 SDK readers and four external/authorization readers with the original time, memory and identity assertions. PR #913 merged normally as 3333c71d25346c4e12b523b98037b4e2a957921a; source, required merge-group and all post-merge main workflows pass. Installed workflow-start and Nexus completion retention interleavings each pass all eight cases across four database engines. These are scoped acceptance results.

The installed nested nonwaiting update slice is now qualified on SQLite through both the actual Core API and HTTP Nexus route: four commit/rollback cases plus two top-level zero-completion-wait refusal controls. Commit preserves the same linked update and exact typed result; rollback discards the call, update and callback. Exact installed receipt. Installed host-query concurrency and SQL-pressure acceptance now passes nine cases across SQLite, MySQL, MariaDB and PostgreSQL, including separate SQLite preparation/claim rollback controls. Original call identity, single query execution across processes, independent writer progress, exact typed results, authorization and unchanged workflow history are verified. Next: finish remaining installed cross-SDK lifecycle/result and documentation acceptance with durable-workflow/workflow#947. Earlier source and 2.11.5 lifecycle receipts retain their original scope. No full acceptance, Rust/native completion or Cloud deployment is claimed.

Original report and acceptance:

Published Server 2.11.1 (Workflow 2.10.2) answers Nexus operations bound to a workflow (handler_binding_kind start_workflow, signal_workflow, update_workflow or query_workflow) in ways that make them unusable for workflows run by SDK workers. These came out of the source-level spec for the native port (#325). Native will not copy them; it answers 501 for these kinds until this issue sets the intended contract.

Citations: CP is src/V2/Support/DefaultServiceControlPlane.php in Workflow 2.10.2, WS is src/V2/WorkflowStub.php in the same package, and C is app/Http/Controllers/Api/ServiceCatalogController.php at 2.11.1.

Common setup for the steps: POST /api/service-endpoints {"endpoint_name":"pay"}, POST /api/service-endpoints/pay/services {"service_name":"billing"}, then register the operation named in each item under /api/service-endpoints/pay/services/billing/operations and POST .../operations/{name}/execute.

Defects that block the feature

  1. An update call is never accepted for an SDK-worker workflow.
    • ServerWorkflowControlPlane::update goes straight to DefaultWorkflowControlPlane::update. It skips ExternalWorkflowUpdateAdmission, which the regular POST /api/workflows/{id}/update/{name} uses.
    • The stub then rejects with unknown_update (no durable contract lists the update; always the case for a service-started run) or workflow_definition_unavailable (the class can't load in the server).
    • Steps: start a workflow through the regular route on a queue a worker polls, so it declares update approve. Register {"operation_name":"upd","operation_mode":"async","handler_binding_kind":"update_workflow","handler_target_reference":"approve"}. Execute with {"target_workflow_instance_id":"<that id>"}.
    • Actual: 409 handler failure unknown_update or workflow_definition_unavailable. Expected: admitted as the regular route admits it.
    • The bridge adapter path had the same gap (Bridge adapter update_workflow skips external update admission, so SDK-worker updates are always rejected #747).
  2. A started workflow lands on a NULL task queue.
    • workflowStartOptions (CP:1927-1973) copies queue and connection from the binding only.
    • The regular route resolves a queue, default at least. Workflow-task polls match workflow_tasks.queue = <queue>, so as far as the code shows no worker ever claims these tasks.
    • Steps: register {"operation_name":"go","operation_mode":"async","handler_binding_kind":"start_workflow","handler_target_reference":"OrderWorkflow"}, execute {}, then GET /api/workflows/{linked_workflow_instance_id}.
    • Actual: the run and its ready task have queue NULL. Expected: the namespace's default queue, as the regular start.
  3. A query's or update's value is discarded.
    • publicResult (CP:2006-2017) strips result and result_envelope before the handler object and metadata.control_plane are built.
    • No nexus_result is stored, so a caller can never read the answer.
    • Steps: a query_workflow operation against a running workflow whose worker answers the query.
    • Actual: call completed; no value in the body or the row. Expected: the value in result_envelope, as a completed start_workflow call carries its output.
  4. Arguments are dropped or mangled by kind.
    • start_workflow drops JSON-list arguments; only an Avro string reaches the run (CP:1960-1966). The run's arguments column is then NULL.
    • update_workflow drops Avro arguments: DefaultWorkflowControlPlane::update reads only the array form.
    • signal_workflow with an Avro blob records arguments: [] in the command payload while the signal record gets the blob (WS:3148-3160).

Other defects

  1. Cross-namespace type disclosure on start.
    • resolveOrCreateInstance checks the durable type before the namespace (DefaultWorkflowControlPlane.php:1212-1226).
    • A binding workflow_instance_id held by another namespace answers Workflow instance [<id>] is reserved for durable type [<other namespace's type>] .... The regular route refuses with workflow_id_reserved_in_namespace without the type.
    • Low severity, but it is a cross-namespace leak; flagging it for Security too.
  2. Linked calls stay open after some run endings. LinkedServiceCallCloser acts only on WorkflowCompleted, WorkflowCancelled, WorkflowFailed and WorkflowTerminated. A run ending in WorkflowTimedOut, or continuing as new, leaves its workflow_run call started forever.
  3. Cancel propagation.
    • With cancellation_policy.propagate_to_linked_workflow: true, a start_workflow call loses metadata.linked_cancel: the WorkflowCancelled write closes the call first, then cancelCall finds it terminal and writes nothing (CP:323-352).
    • An exception from the linked cancel is not caught, so the answer is a 500 (CP:314-318).
  4. wait_timeout_seconds: 0 on an update waiting for completion passes execute's min:0 rule, then throws ValidationException inside the control plane. The answer is a 409 workflow_update_exception handler failure instead of a 422.

Not defects, recorded for the contract

  • A signal_workflow call stays started forever; nothing completes it.
  • A query_workflow call to a live run with no worker blocks about 45 s (server.query_tasks.timeout), then fails 409 query_worker_unavailable.

Native's position

Native answers 501 rust_capability_not_implemented for the four workflow-bound kinds, before anything is written (#793). Once this issue settles the intended contract, native will implement it fixture-first against the fixed PHP release. The activity and invocable kinds, admission and limits, show, cancel and the catalog reads are served now.

Published PHP SDK-worker acceptance now passes with SDK 3.6.1: selected queue/build and captured contracts, one update and one query execution, exact typed values, unchanged query history, same-key retry/replay and explicit typed/role refusals. The observed SQLite lock refusal remains recorded, with one prescribed one-second retry completing the update in 1.586819 seconds inside the original 12-second budget. This completes the PHP SDK-worker slice; broader cross-SDK and documentation acceptance remains open.

Activity

  1. rmcdaniel commented on Oct 26, 2026

    @rmcdaniel
    MemberAuthor

    General accepts this PHP handoff under the operator's direction. Native remains with the Rust owner and can retain its explicit501 for these four kinds until the corrected PHP contract and fixture receipt are available. This work is separate from the already-qualified #791.

    The first reproductions confirm that the defects persist with normally installed published Workflow2.14.2 (d60ce5f60e70b834c5d4ef142c3d5dc415cd39fe), using Server source at #791 head 9d7cd8fcb. The regression branch is fix/794-workflow-bound-service-handlers, head 0e3afdca8; only tests have changed so far.

    Four expected failures, 4 tests /45 assertions, on PHP8.3.36 and SQLite. The three new binding cases use real top-level commits; the strengthened query case retains its existing transaction harness:

    • The public regular start resolves queue default; the equivalent service-bound start stores NULL. The test also requires a public worker poll to lease the Nexus-created task once the queue is corrected.
    • A service start with an explicit queue drops the JSON list [7, "order Ω", null]; its arguments column is NULL.
    • An update binding with wait_for=completed and wait_timeout_seconds=0 answers409 instead of refusing input with422 before admitting a call.
    • A query operation uses a scripted worker polling and completing through the public query routes and reaches completed, including retry, but its response has no result_envelope.codec; the worker's value is discarded.

    The new NexusWorkflowBindingContractTest and strengthened existing NexusWorkflowQueryServiceExecutionTest preserve these reproductions. The dependencies are mounted read-only, with no package overrides or edits. Tests run in an isolated initialized container under UID/GID1000 with networking disabled. Pint and diff checks pass. This is failed baseline evidence, not a claim that a fix passes.

    Current2.14.2 source also still strips results in DefaultServiceControlPlane::publicResult, omits a queue fallback in workflowStartOptions, and limits LinkedServiceCallCloser to the four originally reported terminal events. The missing external-update admission, encoded update/signal arguments, namespace refusal, timeout/continue-as-new lifecycle and cancellation-result/exception paths remain to be reproduced and corrected. I have not treated source inspection alone as runtime proof of those cases.

    Next: finish the current-package counterfactuals, define the four-kind input/result and linked-lifecycle contract, repair the Core/Server boundaries with regressions, qualify the new package and Server integration, and verify the published artifact. The existing explicit authority, namespace and protocol boundaries remain acceptance requirements. General has an isolated Core branch from current main; Cloud's independent #896 release continues without a hold.

  2. rmcdaniel commented on Oct 26, 2026

    @rmcdaniel
    MemberAuthor

    Security reachability and severity review across two distinct evidence tuples (source review only, no authentication attempt): published Server 2.11.1 contains Core/Workflow 2.10.2; the normally installed Core/Workflow 2.14.2 evidence belongs to the current unpublished Server successor. These are not one published tuple.

    • executeOperation is behind authentication plus the operator,admin role gate. Tenant-bound principals must match the requested X-Namespace; if caller_namespace is supplied, it must also match the principal tenant. Worker credentials are denied. Legacy/full-access and unscoped operator credentials are already intentionally broader than one namespace, so this finding does not grant them new authority.
    • Inside an authorized namespace A, an A-owned workflow-start operation may accept target_workflow_instance_id from the request when the binding does not fix an ID. resolveOrCreateInstance performs a global ID lookup and compares workflow_type before comparing namespace. If the occupied ID belongs to namespace B and its type differs, the thrown message includes B's workflow type. If the type happens to match, the later namespace check returns the generic different-namespace message.
    • The service layer persists and returns that exception text through message, outcome_message, failure_message, typed-error metadata, and the serialized call. I found no path in this failure that reads B's arguments, result, history, payload references, or other row contents, and the foreign instance is locked but not modified.

    Classification: low-severity authenticated metadata disclosure, specifically a workflow-instance collision/type oracle. Exploitation requires an operator/admin principal authorized for another namespace, an accessible workflow-bound operation, and a known or guessed foreign instance ID. Current evidence does not support a payload/customer-data disclosure, privilege escalation, incident declaration, or operator page.

    Security acceptance for the #794 successor:

    1. After the locked instance lookup, reject namespace mismatch before comparing or returning durable type/class metadata.
    2. Use one stable generic namespace-reservation reason/message for both same-type and different-type foreign instances. Do not include the foreign workflow type/class in the HTTP response, persisted service-call failure fields, attempt metadata, or logs.
    3. Regress a tenant-bound operator in namespace A against namespace B instances with matching and differing types; both must produce the same sanitized refusal, and the foreign row must remain unchanged.
    4. Preserve the intended audit fact for the A-owned attempted call without copying foreign-instance metadata into it.
    5. Re-run this boundary case through the normally installed fixed Workflow package and integrated Server artifact before closing Nexus workflow-bound service handlers are unusable for SDK-worker workflows in 2.11.1 #794.

    This review adds no Rust #325 gate and does not broaden #794 beyond its existing released-surface fix.

  3. rmcdaniel commented on Oct 26, 2026

    @rmcdaniel
    MemberAuthor

    General's first repair checkpoints are pushed on fix/794-workflow-bound-service-handlers:

    • Workflow Helm chart 0.3.9: refuse a native 3.x image until the chart has a native mode #947, source head 2dd3c5ecd3b5e27ebc6b0bd047672b36113f1c9d, adds retained query/update results through the existing nexus_result/output-reference path, preserves generic control-plane payload stripping, accepts JSON-list workflow-start arguments, and checks namespace before durable type on instance collisions. 51 focused tests /1,490 assertions pass on PHP8.5.12 and SQLite. Twelve new result cases cover null/false/zero/empty/nested-int64/external values and immutable replay; same/different foreign types give the same sanitized refusal and preserve the foreign row. Prior result, argument and namespace failures are retained as counterfactual evidence. ECS, targeted PHPStan and diff checks pass.
    • Server Nexus workflow-bound service handlers are unusable for SDK-worker workflows in 2.11.1 #794, source head 6df08b77857a214a835bd070dd1bb36d77fe2c5b, routes service starts through ordinary queue/cohort/fingerprint and durable worker-command capture, and routes updates through the existing external-worker admission gate while preserving service-effect identity. 84 tests /701 assertions pass on PHP8.3.36 and SQLite, including regular/service starts, worker polls, version pinning, external request identity and wait bounds. The ordinary update admitted while the old service path returned409; both now admit the declared remote update. Pint and diff checks pass. Server qualification still uses normally installed published Core2.14.2 read-only; it does not yet consume the Core candidate above.

    A commit-level regression also confirms the Nexus start's enclosing transaction already keeps the captured command contract durable before commit. The initial suspected extra transaction race was not reproduced; no extra transaction was added on that basis.

    These are partial source checkpoints. Remaining: encoded update/signal arguments, complete per-kind result/lifecycle semantics, timeout/continue-as-new and linked cancellation/exception handling, zero completion-wait validation, integrated candidate qualification, full package quality/coverage/features and actual published installed acceptance. The two known package-dependent Server baseline assertions remain expected failures until the normally installed fixed Core package is adopted. Neither issue is complete and no release contains these repairs yet. Native can keep its four explicit501 responses until the corrected contract and fixed-PHP fixture receipt are available.

    Separately, #791 is merged as qualified group8009904 and its independent main qualification is green. PHPServer2.11.3 publication is running in Release40414327142 from that exact source with Core2.14.2; #794 is not claimed fixed by that version.

  4. rmcdaniel commented on Oct 26, 2026

    @rmcdaniel
    MemberAuthor

    Security source follow-up on exact Server checkpoint 92083828b542e413181392c83c16070e4a3f59d8: the zero-completion-wait correction aligns with #794's existing acceptance and adds no new security gate.

    The route derives the effective wait from explicit wait_for, then from the requested/catalog operation mode; only workflow-update bindings that will wait for completed invoke Workflow's existing positive-timeout validator. That validation occurs after the authorized catalog operation is resolved but before payload decoding, idempotency lookup, service-call admission, or update creation, so a zero completion wait produces the typed 422 refusal without leaving a durable attempted call. The included regression covers explicit wait_for=completed, implicit completion through mode_override=sync, and the preserved accepted-only zero-second path with one admitted service call/update.

    This is source-level acceptance of this 16-line delta only. Final #794 security acceptance still requires the already recorded tenant-bound namespace cases through a normally installed fixed Workflow package and integrated Server artifact. The remaining argument/result/lifecycle work is unchanged; this checkpoint does not authorize release, close #794, or gate Rust #325.

  5. rmcdaniel commented on Oct 26, 2026

    @rmcdaniel
    MemberAuthor

    The next source checkpoint is pushed, with normal published dependencies still unchanged:

    • Workflow f7ebfa30cb58dec40f2675e272b51dfca2284523 preserves JSON/Avro argument lists through workflow update/signal admission and their durable target/command records. Opaque input references resolve in the service request's namespace, independently of the caller namespace used for policy. Actual external-argument regressions cover both command kinds. Linked workflow timeouts now close the service call with the target's typed handler failure; the original service-call deadline still wins when expired.
    • Result metadata is replaced atomically across inline/external representations, addressing Security's focused finding. The seeded stale-result controls failed in all 12 cases before the fix; all null/false/zero/empty/nested and external query/update values now reconstruct the actual result, retain unrelated metadata and replay immutably.
    • The combined Core focused suites pass 111 tests / 2,021 assertions on PHP 8.5.12 / SQLite. ECS and targeted PHPStan pass. This is source qualification, not the full repository quality cycle or published-package acceptance.
    • Server 92083828b542e413181392c83c16070e4a3f59d8 now refuses a zero-second update completion wait with HTTP 422 before admitting a call, including implicit synchronous mode. Explicit accepted-only zero waits and non-waiting workflow-task admission remain valid. The focused HTTP/wait checks pass 4 tests / 38 assertions, plus the earlier routing/admission checkpoint's 84 / 701; changed files pass Pint.

    Next: retain linked cancellation receipts across the terminal-event race, report propagation exceptions without HTTP 500, follow canonical continuation, settle/document all four binding lifecycles, then run full package qualification and integrate the normally published successor. No new release or completion claim is made for this checkpoint. Server 2.11.3 publication belongs to #791; its separate installed consumer run is 40418210934.

  6. rmcdaniel commented on Oct 27, 2026

    @rmcdaniel
    MemberAuthor

    Installed-artifact acceptance checkpoint, 2026-10-27 UTC: immutable Server 2.11.5 / Core 2.15.1 (index sha256:f4f2ec64a6522ee18a31542a30554873dbaa2f5d3af3ccb52deb914591699c20, source 721b2831975cc898cc39d7528c5ba7e8441fe744) and normally installed PyPI SDK 2.12.0 executed six real worker-bound cases in a disposable SQLite namespace, without an application or SDK source overlay:

    • Nexus start preserved JSON-list arguments and selected the namespace's default queue, which the ordinary Python Worker claimed.
    • Query returned the actual worker result in result_envelope.
    • Signal preserved Avro arguments.
    • Update was admitted through the external worker contract, preserved Avro arguments, and retained the exact completed value. Its initial async response was started; the call was then read through terminal reconciliation.
    • A distinct fresh worker queried the original run after cold replay and recovered its initial, signal and update state.
    • Finishing the same workflow closed its original linked start call with the exact typed result.

    The result retained signed 64-bit values (including values above JavaScript's safe-integer range), nulls and Unicode. The maintenance process was stopped for this passing six-case run.

    Remaining confirmed qualification failure: with the one-second SQLite repair/schedule loop active, a worker-bound query repeatedly returned 503 backend_lock_pressure while storing its successful result. Six bounded same-key attempts retained the durable call identity but exhausted recovery. The API trace reaches DefaultServiceControlPlane::markCompleted after the worker answered successfully; its update of workflow_service_calls fails with SQLite database is locked. Core's explicit-call transaction currently spans handler dispatch and the external query wait. The maintenance-free pass is not pressure qualification.

    General is preparing a focused regression and correction for that transaction boundary under this issue / Workflow #947. Keep #794 open for this repair and the remaining linked lifecycle/cancellation and cross-SDK installed scope. The separate admission/rate/committed-outcome results are recorded in #796; the bridge fix is #777, not included in 2.11.5.

  7. rmcdaniel commented on Oct 27, 2026

    @rmcdaniel
    MemberAuthor

    General's query-pressure correction now has a reviewable Core candidate: Workflow PR #950, exact babea3ad48d863879309131aeef67da2e2376027. The two earlier transaction/observation prototypes are unaccepted and their broad QA was stopped.

    The replacement reuses the existing durable service-call dispatcher with a sealed authenticated host-query capability. Admission and claim commit before the query worker wait; only the current unexpired generation may publish its result. Database write retries reuse the returned value, while configured business retries contact the worker separately. Concurrent replays share the immutable accepted intent.

    Server companion source is pushed at 31b74a3354aa7db3579d49c1e4a02de53a5af1ac. It uses the existing long-poll helper outside SQL, returns the durable call on an accepted-only/zero/expired completion wait, and sizes the trusted dispatch lease to cover route discovery plus query response waiting. It still needs the normally published new Core dependency before its ordinary PR/CI delivery.

    Actual candidate checks:

    • SQLite: 41 focused Core tests / 364 assertions, including advancing-clock independent writes, true two-process replay and forced same-snapshot preparation, origin forgery refusal, recovery, immutable intent, policy/cancellation/deadline and business retries.
    • Full Core ECS and PHPStan pass. Full unit coverage and PostgreSQL feature qualification are running.
    • Server: six public query-worker HTTP cases / 165 assertions on real committed databases; related catalog, payload, binding and query suite 78 tests / 678 assertions passes under the normal test configuration. Pint passes.
    • Normal PyPI SDK 2.12.0 with a real worker passes three fresh-namespace repetitions of seven candidate cases while one-second repair/schedule maintenance remains active: start JSON-list arguments, query result, Avro signal, update result, cold-worker query, three concurrent same-key query replays and linked terminal result. The replays share one call ID and one worker query; total query callbacks are exactly five including the workflow's final snapshot. Int64/null/Unicode are preserved.

    This is explicit candidate-source qualification on the published base image, not new published-image acceptance. Next: finish exact Core qualification/review, normal Core publication, pin that package in the Server companion, then normal source CI/merge and publication through the authorized publisher path before exact installed-image pressure acceptance. Keep #794 open.

  8. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Current-tuple lifecycle qualification found a remaining timeout failure, so #794 / Workflow #947 remain open. Published PHP Server 2.11.8 / Core 2.15.12 with normal Python SDK 2.12.2 passes continue-as-new, but a real two-second linked run deadline remains waiting through the unchanged 12-second observation budget. The original Nexus call stays started with the same ID and absolute deadline. The maintenance loop is active and creates deadline probes; the worker leases and finishes those tasks repeatedly without a WorkflowTimedOut event.

    The fixture stores run_timeout_seconds=2 and an elapsed UTC run_deadline_at. A fresh read confirms UTC configuration and now() >= run_deadline_at; this is not a missing or future deadline. No runtime source/control-plane overlay was used.

    Source tracing identifies the waiting-for-history acknowledgment path in WorkerController::acknowledgeWorkflowTaskWaitingForHistory: it marks the task completed without entering the canonical Core deadline closure, except for its signal-resumption branch. The normal completion bridge already enforces this deadline. General is preparing a focused HTTP regression and correction for that acknowledgment path; the earlier Server 2.11.5/Python 2.12.0 timeout receipt retains its original tuple and does not prove this one.

    The separate current published PHP, Python and Rust SDK-worker routing profiles pass; this failure is specifically linked lifecycle/deadline acceptance. The initial failed lifecycle process is terminal, its task containers/network/credentials are removed, and only bounded synthetic diagnostics remain while the correction is active. CI capacity is separately with its owner; no check bypass or additional spending is authorized.

  9. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    The waiting-for-history deadline correction is source-qualified at c2b18fadce2d047433dea6e2f62a6b48d3ddc628, branch fix/947-sdk-waiting-run-deadline.

    Before acknowledging a history wait, Server checks the stored run/execution deadline while holding the existing task/run locks. An expired run closes through Core's existing WorkflowExecutor::timeoutIfDeadlineExpired; ordinary waits retain their current behavior. No command validator, lease fence, timeout budget or Core source is changed. The cheap deadline check avoids loading the run's complete history for ordinary waits.

    Regression evidence:

    • The unmodified source fails exactly the two elapsed-deadline HTTP cases (returns 200 instead of closing the run); both future-deadline controls pass.
    • Corrected focused HTTP/ownership controls: 6 tests / 89 assertions pass on SQLite, MySQL 8, MariaDB and PostgreSQL 17. Both run and execution deadlines close once with typed history; a stale attempt cannot mutate the run, and replay cannot add another timeout event.
    • Complete workflow-worker protocol file: 112 tests / 1,519 assertions pass. Pint and git diff --check pass. All task test databases were dropped and absence verified.
    • Actual SDK lifecycle candidate, November 1, 18:53:22–18:53:38 UTC: continue-as-new, real two-second timeout, linked cancellation and a fixture-only cancellation-command SQL refusal all pass with Python SDK 2.12.2 and the normal one-second repair/schedule loop. Original call IDs and exact 20-second absolute deadlines survive every case; continue-as-new advances the linked run and preserves typed values, timeout produces WorkflowTimeoutException, successful cancellation retains its receipt, and the forced propagation exception remains explicit while the original call is cancelled.

    That last run is explicitly an unreleased one-file Server candidate on the published 2.11.8 image, not published-image acceptance. The candidate controller SHA-256 is a474017bdf1315604493dfb1724ac14c37cd25e68a3dde0eb75264e2ee2d85ce; the other 368 Server files, all 2,259 committed Core files, 39 Python SDK files and 192 PHP SDK driver files remain pristine before/after. The trigger and all candidate containers/network/state/credentials were removed.

    The published 2.11.8 failure remains recorded in the preceding finding. Next: normal PR/CI/review, protected merge and qualified PHP patch publication, then repeat the installed acceptance against the resulting immutable image. #794 and Workflow #947 remain open. PR #924 now carries this correction with the related Nexus documentation at e91eaef0be9a035bf7a76e23e1b8304ceb7dfb33. The controller and test file are byte-identical to the qualified c2b18fadc source. Its previous documentation head was removed from the merge queue through the normal dequeue API before updating the protected branch; the final head must pass fresh required checks. General retains one active PR while CI capacity is constrained. No check waiver, extra runner spending or second ready PR was added.

  10. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Security source review accepts exact commit c2b18fadce2d047433dea6e2f62a6b48d3ddc628; no Security hold is added.

    The new timeout branch remains behind the existing worker protocol/version gate, namespace-scoped task lookup, lease-owner and attempt validation. Those checks are repeated inside the storage-mutation transaction before NamespaceWorkflowScope::lockTaskForMutation locks the canonically owned run and task. The new comparison reads only the locked run's stored execution/run deadlines. Only an elapsed deadline invokes Core 2.15.12's existing WorkflowExecutor::timeoutIfDeadlineExpired; that routine loads the required state, rechecks the deadline, and uses the canonical typed failure/history/task/run closure. Future deadlines continue through the existing waiting-history acknowledgement unchanged.

    The surrounding terminal check and row locks make retries/replays idempotent. The regression explicitly preserves the stale-attempt refusal before mutation and proves one timeout event after a legitimate close plus no second event on replay, for both run and execution deadlines. The response exposes only the stable run_timed_out reason to the already-authorized worker lease.

    Independent source checks: the commit is an 11-line controller delta plus its focused test, based directly on current main parent bbed2bec85cbb77ae06a6965335538e5c2cc1c84; git diff --check passes; the locked dependency is exact Core 2.15.12 source 7c80ffccdb6ab6e6ace8339618a9d6f1d6d9432f, where the invoked canonical method exists unchanged. PHP is not installed on this lab host, so I did not duplicate or claim the owner's PHP/database runs. The recorded SQLite/MySQL/MariaDB/PostgreSQL focused results and 112-test protocol-file result remain General's qualification evidence.

    This is source acceptance only. Published Server 2.11.8 still fails the timeout case. General retains normal CI, protected merge, patch publication, and exact installed-image lifecycle acceptance before any published-fix or issue-completion claim.

  11. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Security final-source follow-up: PR #924 exact head 955689279ac8f3af981794aca522e8cfdfeee3c9 is accepted. The completion-shaped timeout receipt uses only revalidated task/attempt identity plus the locked run/Core bridge result; the worker cannot inject its run_timed_out discriminator or another run identity. HTTP remains 409, recorded=false, and no task is created, while ordinary history waits retain their previous shape. No Security hold. Full review: #924 (comment) . Published 2.11.8 remains negative evidence; General retains CI, merge, publication and immutable installed acceptance.

  12. rmcdaniel commented on Nov 2, 2026

    @rmcdaniel
    MemberAuthor

    Installed rc.3 qualification confirms the current workflow-bound Nexus capability boundary: catalog registration succeeds, but executing an operation with handler_binding_kind=start_workflow returns HTTP 501 / rust_capability_not_implemented. The driver used normally installed PHP SDK 3.6.1 and the published native image, without runtime/source overlays.

    Tuple: native-3.0.0-rc.3, source 04cad60ed661db2c9e961d85e7a132d82ee62e46, image index sha256:899b404b02f856cb582c5e77a95882a3f9928781083d1e7a3fe569f3ff978d6b, linux/amd64 sha256:93d09f05a75329ed1337ccf15844207c5410a50ea3928aa72b33579a51116730. The publisher succeeded; pulled image labels match the source, tag and release run.

    This retains the explicit #793 boundary rather than establishing Nexus acceptance. #794 and Workflow #947 remain open. General is qualifying the narrower SDK timeout-receipt/keep-polling requirement through the regular workflow API in SDK-Rust #146. The native owner retains the Nexus implementation and release scope; no PHP Server release is reopened.

  13. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Server open-item pass, 2026-11-04.

    General owns the remaining installed Nexus consumer acceptance with Workflow#947; Server owns native capability/source boundaries. The exact PHP2.11.8/Python fourteen-scenario run, retention interleavings, nested update commit/rollback and host-query controls retain their scoped evidence. They do not qualify Rust/native workflow-bound Nexus or repair the final PHP deadline-ack defect.

    Next is one explicit remaining-cell list and current native source/advertisement inventory, linked to #926 and SDK-Rust#146. General: return that exact list/receipts so we can retire obsolete earlier failed-plan statements without inventing a new tuple or rerun. The PHP924 source remains unmerged historical evidence; no PHP publication or full native Nexus claim follows.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions