Skip to content

fix: bind queued chat messages to the session owner #451

Description

@chubes4

Problem

PR #450 at 87e14c8478d580e6e144c2642fa027dc1a58156f scopes queue persistence by canonical workspace and fingerprints each queued item, but enqueue authorization is not bound to the target session/run owner.

Any authenticated user can provide their own valid session_owner with another principal's known session_id in the same workspace. agents_chat_run_enqueue_permission() accepts the self-owned claim, and WP_Agent_Chat_Run_Control::queue_message() appends the item without verifying that the referenced run/session belongs to that owner.

The legitimate owner's next claim_queued_messages() call then filters out the foreign item and returns an empty array when the filtered count differs from the full queue. It does not remove either item, so the foreign item can indefinitely block continuation claims for that session.

Reproduction

Against PR #450 head:

  1. Create workspace run/session network-session for owner user:123.
  2. As WordPress user 456, queue a message with the same workspace and session_id, but principal/session owner user:456.
  3. Permission and enqueue both succeed.
  4. Claim the queue as owner user:123.
  5. The claim returns no messages.

Observed result:

{"foreign_allowed":true,"foreign_queued":true,"owner_claim_count":0}

Relevant code

  • src/Channels/register-agents-chat-run-control-abilities.php:281-307 and :334-341: enqueue permission verifies that the caller matches the supplied owner claim, not that the target session/run does.
  • src/Runtime/class-wp-agent-chat-run-control.php:270-294: queue insertion does not verify the referenced run/session owner.
  • src/Runtime/class-wp-agent-chat-run-control.php:313-323: one foreign-owned item makes the legitimate owner's claim fail closed without clearing the poison item.
  • tests/chat-run-control-multisite-smoke.php: covers wrong-principal run reads and forged cancellation, but not wrong-principal enqueue/claim isolation.

Required contract

  • Reject enqueue when the target run/session is not owned by the resolved principal.
  • Ensure one principal cannot block another principal's queue claims.
  • Add multisite workspace coverage for wrong-principal enqueue and mixed-owner queue state.
  • Preserve omitted-workspace compatibility.

This blocks treating #450 as a complete foundation for Extra-Chill/extrachill-roadie#86 because #449 explicitly requires principal/session ownership across queue/continuation paths.

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