Skip to content

Message stream appends are accepted on read-only Waterline v1 projections #769

Open

Description

@rmcdaniel

Published Server 2.11.1 accepts a message stream append to a read-only Waterline v1 projection.

Behavior. POST /api/workflows/{workflowId}/message-streams/{streamName}/messages (MessageStreamController::append, MessageStreamService::append) never checks whether the instance's current run is a Waterline v1 projection (import_source = waterline_v1_projection). For a projection in an open status (pending, running or waiting), a valid append:

  • creates the inbound stream and item;
  • delivers a signal with its command and history event;
  • creates a workflow task for a run whose execution is owned by the v1 runtime.

An invalid body still records malformed-input state on the projection's stream.

Why it matters. Every other run operation refuses a projection with v1_projection_read_only before reading its body (WorkflowController::rejectProjectedV1Operation / projectedV1OperationResponse: signal, query, update, cancel, terminate, repair, archive, redrive). The append path breaks the projection's read-only, no-tasks contract, and gives workers an execution path into a v1-owned run.

Expected. The append is refused with 409 v1_projection_read_only before the body is parsed. The service also checks under its lock, so a direct call cannot write any stream, item, signal, command, history, task or summary state. Malformed input is not counted against a projection.

Native. Server #768 (Rust #325) adds that refusal at the route and the service, plus a locked check in the store transaction. Its tests show valid and invalid appends, a direct service call and a direct store call change no rows. That will differ from published 2.11.1 until PHP is fixed.

Found by Security's review of #768. Handed to the General owner for the PHP fix.

Activity

  1. added a commit that references this issue on Oct 25, 2026
  2. rmcdaniel commented on Oct 25, 2026

    @rmcdaniel
    MemberAuthor

    Handoff record. The General owner accepted the PHP fix in the native agent chat (server-325, 2026-10-25 22:58 UTC). The planned shape:

    • A request-time refusal before the body is parsed (the HTTP fence).
    • A check inside MessageStreamService's locked transaction, before both the duplicate-replay update and the new item, so a direct service call cannot write either.
    • No malformed-input counting against a projection.

    Native counterpart. Server #768 does the same in three places: the route, the service, and the store transaction under its serialization lock. Its tests cover valid, invalid and non-object appends, direct service and store calls, and a lock-barrier control showing that an append cannot cross a projection install.

    Merge ordering. Native #768 can merge first and is documented as ahead of published 2.11.1 here. This issue stays open until the PHP Server has the fix and a parity fixture covers it.

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