diff --git a/src/Transcripts/register-agents-conversation-session-abilities.php b/src/Transcripts/register-agents-conversation-session-abilities.php index 07e05de..1dc1239 100644 --- a/src/Transcripts/register-agents-conversation-session-abilities.php +++ b/src/Transcripts/register-agents-conversation-session-abilities.php @@ -479,7 +479,7 @@ function agents_conversation_sessions_owned_session( string $session_id, array $ if ( $context['store'] instanceof WP_Agent_Principal_Conversation_Session_Reader ) { $session = $context['store']->get_session_for_owner( $workspace, $context['owner'], $session_id ); if ( ! is_array( $session ) ) { - return new \WP_Error( 'agents_conversation_session_not_found', 'Conversation session not found.' ); + return new \WP_Error( 'agents_conversation_session_not_found', 'Conversation session not found.', array( 'status' => 404 ) ); } return agents_conversation_sessions_array_value( $session ); @@ -487,12 +487,12 @@ function agents_conversation_sessions_owned_session( string $session_id, array $ $session = $context['store']->get_session( $session_id ); if ( ! is_array( $session ) ) { - return new \WP_Error( 'agents_conversation_session_not_found', 'Conversation session not found.' ); + return new \WP_Error( 'agents_conversation_session_not_found', 'Conversation session not found.', array( 'status' => 404 ) ); } $session = agents_conversation_sessions_array_value( $session ); if ( ! agents_conversation_sessions_session_matches_owner( $session, $context['owner'] ) && ! agents_conversation_sessions_can_manage_any() ) { - return new \WP_Error( 'agents_conversation_session_forbidden', 'The current principal cannot access this conversation session.' ); + return new \WP_Error( 'agents_conversation_session_forbidden', 'The current principal cannot access this conversation session.', array( 'status' => 403 ) ); } return $session; diff --git a/tests/agents-conversation-session-abilities-smoke.php b/tests/agents-conversation-session-abilities-smoke.php index e7e4ebb..939997c 100644 --- a/tests/agents-conversation-session-abilities-smoke.php +++ b/tests/agents-conversation-session-abilities-smoke.php @@ -18,9 +18,10 @@ if ( ! class_exists( 'WP_Error' ) ) { class WP_Error { - public function __construct( private string $code = '', private string $message = '' ) {} + public function __construct( private string $code = '', private string $message = '', private mixed $data = null ) {} public function get_error_code(): string { return $this->code; } public function get_error_message(): string { return $this->message; } + public function get_error_data(): mixed { return $this->data; } } } @@ -255,6 +256,7 @@ public function update_title( string $session_id, string $title ): bool { $forbidden = agents_get_conversation_session( array( 'principal' => $other_principal, 'session_id' => 's-1' ) ); smoke_assert( true, $forbidden instanceof WP_Error, 'get blocks sessions owned by another user', $failures, $passes ); smoke_assert( 'agents_conversation_session_forbidden', $forbidden instanceof WP_Error ? $forbidden->get_error_code() : '', 'forbidden error code', $failures, $passes ); +smoke_assert( 403, $forbidden instanceof WP_Error ? ( $forbidden->get_error_data()['status'] ?? null ) : null, 'forbidden error carries REST status', $failures, $passes ); $audience_without_owner = WP_Agent_Execution_Principal::audience( 'audience:public', 'demo-agent' ); $owner_required = agents_list_conversation_sessions( array( 'principal' => $audience_without_owner ) ); @@ -369,6 +371,7 @@ public function update_title( string $session_id, string $title ): bool { $this- $other_audience = WP_Agent_Execution_Principal::audience( 'audience:public', 'demo-agent', WP_Agent_Execution_Principal::REQUEST_CONTEXT_REST, array(), null, null, array(), 'browser:two' ); $blocked_owner = agents_get_conversation_session( array( 'principal' => $other_audience, 'session_id' => 'p-1', 'workspace' => array( 'workspace_type' => 'site', 'workspace_id' => '42' ) ) ); smoke_assert( 'agents_conversation_session_not_found', $blocked_owner instanceof WP_Error ? $blocked_owner->get_error_code() : '', 'principal owner key blocks other audience sessions', $failures, $passes ); +smoke_assert( 404, $blocked_owner instanceof WP_Error ? ( $blocked_owner->get_error_data()['status'] ?? null ) : null, 'foreign principal read carries non-enumerating REST status', $failures, $passes ); // REST callers cannot impersonate other owners via the principal field — the // principal is resolved from the request, not from the body. @@ -392,6 +395,7 @@ public function update_title( string $session_id, string $title ): bool { $this- ) ); smoke_assert( 'agents_conversation_session_not_found', $forged_get instanceof WP_Error ? $forged_get->get_error_code() : '', 'REST principal passthrough is ignored on get', $failures, $passes ); +smoke_assert( 404, $forged_get instanceof WP_Error ? ( $forged_get->get_error_data()['status'] ?? null ) : null, 'missing REST session carries not-found status', $failures, $passes ); $forged_list = agents_list_conversation_sessions( array(