Skip to content

WorkflowStub::make()->start() ignores workflows.v2.namespace while WorkflowControlPlane::start() applies it #617

Description

@chrom

Owning public component

Workflow engine

Exact version or source identity

2.4.0.

Minimal reproduction and evidence

Observed with durable-workflow/workflow 2.4.0 in a Laravel application using PostgreSQL and the database queue driver.

The package exposes DW_V2_NAMESPACE, mapped to workflows.v2.namespace.

Run the following after bootstrapping Laravel with the Workflow service provider registered:

use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Workflow\V2\Attributes\Type;
use Workflow\V2\Contracts\WorkflowControlPlane;
use Workflow\V2\Models\WorkflowInstance;
use Workflow\V2\Models\WorkflowRun;
use Workflow\V2\Workflow;
use Workflow\V2\WorkflowStub;

#[Type('namespace-probe')]
final class NamespaceProbeWorkflow extends Workflow
{
    public function handle(): string
    {
        return 'ok';
    }
}

Bus::fake();

$originalNamespace = config('workflows.v2.namespace');
config(['workflows.v2.namespace' => 'default']);

$stubId = 'namespace-probe-stub-' . Str::uuid();
$controlId = 'namespace-probe-control-' . Str::uuid();

DB::beginTransaction();

try {
    $started = WorkflowStub::make(
        NamespaceProbeWorkflow::class,
        $stubId,
    )->start();

    app(WorkflowControlPlane::class)->start(
        NamespaceProbeWorkflow::class,
        $controlId,
    );

    dump([
        'configured_namespace' => config('workflows.v2.namespace'),
        'stub_instance_namespace' => WorkflowInstance::query()
            ->findOrFail($stubId)->namespace,
        'stub_run_namespace' => WorkflowRun::query()
            ->findOrFail($started->runId())->namespace,
        'control_run_namespace' => WorkflowRun::query()
            ->where('workflow_instance_id', $controlId)
            ->firstOrFail()->namespace,
    ]);
} finally {
    DB::rollBack();
    config(['workflows.v2.namespace' => $originalNamespace]);
}

The equivalent probe was executed with an existing trivial application workflow. The observed values were:

{
  "configured_namespace": "default",
  "stub_instance_namespace": null,
  "stub_run_namespace": null,
  "control_run_namespace": "default"
}

The transaction was rolled back. A subsequent query confirmed that neither probe instance nor its runs remained in the database.

Source inspection also shows:

  • src/config/workflows.php declares the namespace setting.
  • DefaultWorkflowControlPlane::resolveNamespace() reads it.
  • The inspected WorkflowStub::make()->start() path does not apply it when creating the instance and run.

Observed behavior

Setting workflows.v2.namespace does not produce consistent results across the two PHP start APIs:

  • WorkflowStub::make()->start() creates an instance and run with namespace = NULL.
  • WorkflowControlPlane::start() creates a run with the configured namespace.

There is a related operational consequence in our application: schedules use namespace = "default", while runs started through the stub path have namespace = NULL.

Filtering runs by the schedule's namespace therefore returns no matching executions, even though those executions exist and complete successfully.

This was initially visible in a read-only diagnostic tool. No execution failure was demonstrated; the confirmed problem concerns namespace assignment and namespace-filtered visibility.

Expected behavior and acceptance criteria

A configured namespace should have consistent semantics across supported PHP start APIs.

Acceptance criteria:

  1. With workflows.v2.namespace = "default", a new instance and run created through WorkflowStub::make()->start() receive that namespace.
  2. Cover both caller-supplied instance IDs and automatically generated IDs.
  3. Verify namespace propagation to durable tasks where the namespace is part of the task contract.
  4. Verify the standard PHP schedule-start path. A schedule's namespace and its execution namespace should follow an explicit, documented rule.
  5. Preserve the documented behavior when no namespace is configured.
  6. Define behavior when an existing instance belongs to a different namespace; do not silently reassign it.
  7. Add regression tests comparing the stub and control-plane start paths.

If namespace configuration is intentionally unsupported by WorkflowStub, document that limitation explicitly and provide a supported way to start a namespaced PHP workflow through this API.

Existing records should not be rewritten implicitly as part of the fix.

Dependencies and related public issues

Affected package:

  • durable-workflow/workflow 2.4.0

Verified application environment:

  • PHP 8.4.24
  • Laravel 13.34.0
  • PostgreSQL 17
  • Laravel database queue driver
  • Redis cache

Relevant package components:

  • Workflow\V2\WorkflowStub
  • Workflow\V2\Contracts\WorkflowControlPlane
  • Workflow\V2\Support\DefaultWorkflowControlPlane
  • Workflow\V2\Support\ScheduleManager
  • Workflow\V2\Support\PhpClassScheduleStarter

Relevant configuration:

  • DW_V2_NAMESPACE
  • workflows.v2.namespace

The discrepancy was reproduced directly through PHP APIs. Waterline and MCP are not required to reproduce it.

No related public issue has been confirmed for this namespace discrepancy.

Public intake checks

  • I searched open and closed GitHub issues for an existing report.
  • This report contains only public product context and redacted evidence.

Activity

  1. added
    authority:githubGitHub is the authoritative lifecycle record for this work
    kind:defectA public product behavior is incorrect
    priority:untriagedMaintainers have not assigned a priority
    status:triageAwaiting maintainer classification
    on Oct 6, 2026
  2. added
    intake:approvedCurrent issue title and body revision is approved for authority intake
    priority:P1High-priority product or release risk
    status:in-progressApproved work is actively being implemented or validated
    and removed
    priority:untriagedMaintainers have not assigned a priority
    status:triageAwaiting maintainer classification
    on Oct 6, 2026
  3. rmcdaniel commented on Oct 6, 2026

    @rmcdaniel
    Member

    Published Workflow 2.4.2 at 4fcb23622147dd2c1f92e461e927577092120bb8
    passes the fresh installed namespace consumer: 15 cases / 223 assertions. This
    includes actual PHP task execution, scoped visibility, PHP schedule starts and
    unchanged records after rejected conflicting starts.

    Server #304 is merged at ce14b0c20ba1c9486138a0baf830b567e5ee0e36. All final
    PR and merged-main gates pass. Immutable Server 2.5.2 is published from that
    source. Its protected release checks
    pass both architectures/registries, bare-image first-run readiness, source-free
    Compose, catalog convergence and anonymous Helm 0.1.139 installation. Index
    digest: sha256:e5b9043da1c37f3783b6aa91b1638d1ca688539d14d6db2c0e4387731cff88a2.
    The completed remote branch is deleted and verified absent.

    That exact image passes all 14 published namespace scenarios, no findings, and
    all 12 published PHP/Python/Rust lifecycle cells.
    All 15 schedule qualification scenarios pass with no findings, including
    cadence, restart recovery, official CLI and SDK operations, PHP/Python
    cross-language execution and verified published installs. Site
    durable-workflow/durable-workflow.github.io#162 is merged at
    ec3555c8be6c999824ddae6affb26662463a0af0, preserving its qualified tree.
    The local build, all PR/main checks and Pages publication pass. Live installation
    pins show Workflow 2.4.2 / Server 2.5.2. The published
    PHP namespace rules
    and schedule propagation rules
    are verified. Its completed remote branch is deleted and verified absent.

    Sample App #141 is merged and delivered. Both application and microservice locks
    use 2.4.2. PHP, Compose, polyglot and published-image checks passed, including
    anonymous artifact qualification on amd64 and arm64 in
    run 37486553433.

    All acceptance criteria and affected published-consumer follow-through are
    complete. The portable protocol and SDK packages are unchanged. Upgrade embedded
    applications to Workflow 2.4.2 or use Server 2.5.2. Existing records are not
    rewritten by the fix.

  4. added
    status:doneDerived from the authoritative closed issue state
    and removed
    status:in-progressApproved work is actively being implemented or validated
    on Oct 6, 2026
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

    authority:githubGitHub is the authoritative lifecycle record for this workintake:approvedCurrent issue title and body revision is approved for authority intakekind:defectA public product behavior is incorrectpriority:P1High-priority product or release riskstatus:doneDerived from the authoritative closed issue state

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions