Files
support_backend/specs/011-agent-ticket-queue/spec.md
T
saqib mirandClaude Sonnet 5 d58bc98c7f docs(011-agent-ticket-queue): spec for agent-user linking and assigned-ticket listing
Discovered while starting supporthub-web's 001-agent-admin-ui planning:
its agent-dashboard user story needs to list tickets currently assigned
to an agent, and no such query exists anywhere in the ticketing or
orchestration modules. Also finishes wiring Agent.userId (added in
010-identity-auth as schema-only, never consumed by any workflow) so a
logged-in session can resolve to its own agent roster row at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:55:41 +05:30

8.1 KiB

Feature Specification: Agent Ticket Queue

Feature Branch: 011-agent-ticket-queue

Created: 2026-09-07

Status: Draft

Input: User description: "Give agents and the frontend a way to list tickets currently assigned to a given agent, with enough summary detail (customer, product, priority, status, SLA state) to power an agent dashboard, since no such query exists anywhere in the ticketing or orchestration modules today."

User Scenarios & Testing (mandatory)

User Story 1 - An admin links a staff account to its agent roster entry (Priority: P1)

An admin connects an existing User account (role AGENT, from 010-identity-auth) to its corresponding Agent roster row (from 006-support-organization), so the platform knows which login belongs to which routing/skills profile.

Why this priority: Every other story here depends on resolving "this logged-in session" to "this agent's roster row." Agent.userId was added in 010-identity-auth specifically for this purpose but has never been set by any workflow — this is that missing workflow.

Independent Test: Create a User (role AGENT) and a separate Agent roster row; link them via the admin endpoint; confirm the link is retrievable and that linking a User already linked to a different Agent is rejected.

Acceptance Scenarios:

  1. Given an unlinked Agent and a User with role AGENT not yet linked to any agent, When an admin links them, Then the Agent row's userId is set and retrievable.
  2. Given a User already linked to Agent A, When an admin attempts to link that same User to Agent B, Then the request is rejected (the existing unique constraint on Agent.userId is surfaced as a clear conflict, not a raw database error).
  3. Given a User whose role is ADMIN rather than AGENT, When an admin attempts to link it to an Agent row, Then the request is rejected — an Agent roster row represents a working agent, not an admin-only account.

User Story 2 - An agent retrieves their own currently-assigned tickets (Priority: P1)

An authenticated agent (or an admin looking at a specific agent, for support purposes) can retrieve a list of every ticket currently assigned to that agent, each with enough summary data — customer reference, product, priority, severity, status, and SLA state if a run exists — to power an agent dashboard without a further per-ticket fetch.

Why this priority: This is the entire reason this feature exists — supporthub-web's own agent-dashboard user story (its 001-agent-admin-ui, User Story 1) has no data source without it, and no other endpoint in the ticketing or orchestration modules answers this question today.

Independent Test: With two tickets currently assigned to an agent (via the existing orchestration assignment engine) and a third assigned to a different agent, call the new endpoint as the first agent; confirm exactly the first two are returned, each with the summary fields populated, and the third is absent.

Acceptance Scenarios:

  1. Given an agent with two tickets currently assigned to them, When they call this endpoint, Then both are returned, each including customer reference, product, priority, severity, status, and SLA state (or an explicit absence of one, if no SLARun exists yet).
  2. Given an agent with zero currently-assigned tickets, When they call this endpoint, Then an empty list is returned — not an error.
  3. Given a ticket reassigned away from an agent (its Assignment.isCurrent flips to another agent's row), When the original agent calls this endpoint again, Then that ticket no longer appears.
  4. Given a User session with no linked Agent row at all (User Story 1 never completed for this account), When that session calls this endpoint, Then the response is a clear, specific rejection — never a silent empty list that could be mistaken for "no tickets assigned," and never a raw null-reference error.
  5. Given an admin session, When they call this endpoint for a specific agentId, Then the same summary list is returned for that agent — an admin's own use of the endpoint is explicit about which agent it's asking about, unlike an agent's own call, which is always implicitly about themselves.

Edge Cases

  • What happens if an agent has a ticket assigned whose Problem/Product/CustomerReference was deleted (should not happen under normal FK constraints, but the endpoint's own contract should be explicit): every relation this endpoint reads is a required, non-nullable foreign key already enforced by the schema, so this case cannot occur without a prior data-integrity violation elsewhere: not specifically handled here.
  • What happens if two Agent rows somehow both have isCurrent: true assignments for the same ticket (should be impossible under 007's own assignment invariant)? This endpoint trusts that invariant rather than re-deriving it — it is 007's own concern, not this feature's.

Requirements (mandatory)

Functional Requirements

  • FR-001: The system MUST let an admin set an Agent row's linked User (userId), MUST reject linking a User already linked to a different Agent, and MUST reject linking a User whose role is not AGENT.
  • FR-002: The system MUST let an admin read which User, if any, an Agent row is linked to (already covered by the existing GET /admin/agents/:agentId, which returns the full Agent row — this FR only requires userId not be excluded from that response).
  • FR-003: The system MUST provide an endpoint that returns every ticket currently assigned (Assignment.isCurrent: true) to a given agent, each with customer reference, product, priority, severity, status, and SLA state summarized without a further per-ticket request.
  • FR-004: When called by an agent's own session, the endpoint MUST resolve "which agent" from that session's linked Agent row (User Story 1), never from a client-supplied agent ID — an agent can only ever list their own tickets this way.
  • FR-005: When called by an admin session with an explicit agentId, the endpoint MUST return that agent's tickets — an admin-only capability for support/oversight purposes.
  • FR-006: The system MUST reject a call from a session with no linked Agent row with a specific, distinguishable error — never an empty list.

Key Entities

  • Agent-User Link: The (now finally wired) association between a User account and the Agent roster row it authenticates as, via Agent.userId.
  • Assigned Ticket Summary: A read-only projection of a Ticket plus its current Assignment and (if present) SLARun, shaped for list display rather than full detail.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: An agent's currently-assigned tickets are retrievable in a single request, with zero additional per-ticket requests needed to populate a dashboard-style summary list.
  • SC-002: 100% of sessions with no linked Agent row receive a specific rejection from the new endpoint, never an empty list indistinguishable from "genuinely zero tickets assigned."
  • SC-003: 0% of one agent's currently-assigned tickets are visible to another agent calling the endpoint as themselves.

Assumptions

  • This feature does not add a general-purpose ticket search/filter/list endpoint — only the narrow "tickets currently assigned to a specific agent" query supporthub-web's agent dashboard needs. A broader admin-facing ticket search is explicitly out of scope, deferred until a concrete need names its own filters.
  • Linking (User Story 1) is a one-time admin action per agent, not a self-service flow — an agent does not link their own account; matches 006/010's own existing pattern of admin-managed roster and account provisioning.
  • No pagination is included — an individual agent's currently-assigned ticket count is small enough (bounded by realistic per-agent workload) that a single unpaginated list is sufficient for this feature's scope; revisit if a future feature's data suggests otherwise.