Skip to main content

Milestone 12: Search

Purpose: Agents can search tickets and messages by subject/body (full-text); sender and tag as filters; search integrated into ticket list.

Exit state: FTS on tickets and messages; tRPC search with filters; ticket list search input and results.

Spec reference: §2.11 Search, §5.22 GIN indexes (tickets, messages tsv), §6.10 SearchInput.

Prerequisites: M11. FTS columns and GIN indexes from M01.


12.1 Full-text search backend

Tasks

  1. Search procedure

    • tRPC search: input query (string), optional filters (sender/from_address, tag_ids), tenantId from context. Use websearch_to_tsquery('english', query) for safety; search tickets.tsv and messages.tsv with ts_rank; WHERE tenant_id = ? and (tickets match or messages match). Return unified results: ticket id, ticket_number, subject, snippet (highlight), inbox name; optionally message snippet. Section 2.11. Sender and tag as WHERE filters (not FTS). Pagination (limit/offset or cursor).
  2. Indexes

    • Verify GIN on (tenant_id, tsv) for tickets and messages (M01). Section 5.22.
  3. Ranking

    • Order by ts_rank(tsv, query) desc, then created_at desc. Limit results (e.g. 50).

Acceptance criteria

CriterionStatus
Search returns tickets (and optionally messages) matching query; tenant-scoped; sender and tag filters apply.Pending
Query with special characters (quotes, negation) handled via websearch_to_tsquery; no SQL injection.Pending
Performance acceptable with GIN indexes (test with 10k+ tickets).Pending

12.2 Search UI in ticket list

Tasks

  1. Search input

    • In ticket list (M07): search field (debounced, e.g. 300ms). On submit or debounce: call search tRPC; display results in same list UX (replace or merge with filter results). Section 6.10. Alternatively: search drives list query (ticket list tRPC accepts search param and uses FTS in WHERE). Prefer single list that can be filtered by search + filters.
  2. Combine with filters

    • When search is active, list shows only tickets matching FTS + status/assignee/inbox/tag/date filters. URL can include q= for shareable search link.
  3. Empty state

    • "No results for your search" when search returns empty; suggest clearing search or filters.

Acceptance criteria

CriterionStatus
User can type in search; results update (debounced); list shows matching tickets; filters still apply.Pending
Clear search or empty query shows normal list (or last filters).Pending
URL reflects search query for sharing (optional).Pending
Search results and ticket list stay in sync when tickets change (SSE: ticket.updated, ticket.message_added invalidate list/search queries; Section 4.11).Pending

Milestone 12 sign-off

CriterionStatus
All tasks in 12.1–12.2 complete.Pending
All acceptance criteria met.Pending
Search by subject/body works; sender and tag as filters; UI integrated.Pending
E2E: Search and filters (see INDEX — Testing strategy).Pending
Ready for M13 (Reporting).Pending