Skip to content

POST /conversations/{id}/accept never assigns the conversation for JWT agents, but returns 200 #283

Description

@Harol-Reina

Summary

POST /api/v1/conversations/{id}/accept never makes the caller the owner when called with a JWT. The endpoint passes the caller's user id (JWT sub) where the switchboard expects an agent id; the capacity resolver finds no Agent with that id, and the switchboard returns Success = false, "Agent has no capacity.". The endpoint still answers HTTP 200, so the Web agent workspace shows the "accepted" toast while the conversation stays Offered.

Found by code reading on main @ 3f4590ed (v2.23.0); not reproduced at runtime.

Call chain

  1. src/Verbara.Platform.Api/Endpoints/ConversationEndpoints.cs:145-146 — GetCurrentAgentId(context) is passed to AcceptAsync as the agent id.
  2. ConversationEndpoints.cs:978-990 — GetCurrentAgentId returns the JWT sub, which is the user id.
  3. src/Verbara.Platform.Switchboard/ConversationSwitchboard.cs:92-94 — HasCapacityAsync(tenantId, agentId, …); when false it returns OwnershipResult(false, …, "Agent has no capacity.").
  4. src/Verbara.Platform.Queues/Services/InMemoryAgentCapacityService.cs:59-61 → AgentCapacityResolver.cs:28-30 — IAgentStore.GetByIdAsync(tenantId, agentId) returns null for a user id, which the resolver treats as "agent does not exist", so there is no capacity.
  5. Agent ids never equal user ids: the only Agent creation site is src/Verbara.Platform.Api/Endpoints/AdminEndpoints.cs:453 (AgentId = EntityId.New()).
  6. ConversationEndpoints.cs:147 returns TypedResults.Ok(result) whatever result.Success is.
  7. Web: Verbara.Platform.Web/src/core/api/hooks/use-conversations.ts:127-139 treats any 2xx as success and shows toasts.conversations.accepted.

The comment at ConversationEndpoints.cs:980-986 explains that reading sub first stopped JWT agents from getting a random id. The id is now stable, but it is still a user id, not the agent id.

Why tests stay green

tests/Verbara.Platform.Api.Tests/ConversationEndpointTests.cs:51-58 (AcceptConversation_ShouldReturn200_WhenSwitchboardCallSucceeds) posts with a placeholder id and accepts 200, 400 or 500, so it cannot detect a failed ownership change.

Suggested direction

  • Resolve the caller's Agent in the tenant and pass its AgentId; return a 4xx when the caller has no agent.
  • Map OwnershipResult.Success == false to a non-2xx response (or have the Web check success), so a failed accept is visible.
  • Add an integration test: a JWT user with an Agent row accepts an offered conversation, and the owner becomes that AgentId.
  • Other handlers in the same file also treat GetCurrentAgentId as an agent id (:120,523,768,800,815); they are worth checking for the same mismatch.

Activity

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions