Skip to content

docs: design specs for search-service (backend + sync-worker + frontend)#114

Merged
mliu33 merged 7 commits intomainfrom
claude/search-service-nats-HQVRk
Apr 23, 2026
Merged

docs: design specs for search-service (backend + sync-worker + frontend)#114
mliu33 merged 7 commits intomainfrom
claude/search-service-nats-HQVRk

Conversation

@Joey0538
Copy link
Copy Markdown
Collaborator

@Joey0538 Joey0538 commented Apr 22, 2026

Summary

Adds three design specs for a new NATS request/reply search-service and the surrounding work:

  1. 2026-04-21-search-service-design.md — the new NATS request/reply search service.

    • Two endpoints: chat.user.{account}.request.search.messages and …search.rooms.
    • ES cross-cluster search via wildcard alias (messages-*,*:messages-*) — messages only; spotlight + user-room are local.
    • Per-user restricted-rooms cache in Valkey (5-min TTL, lazy-populated from ES user-room doc on miss).
    • Reuses pkg/natsrouter, flat service layout per CLAUDE.md.
    • Adds pkg/searchengine.Search/GetDoc, pkg/subject builders, pkg/model request/response types, new pkg/valkeyutil package.
    • Valkey + Kibana added to docker-local.
    • Full testing strategy including a CCS integration test using two ES containers on the same Docker network.
  2. 2026-04-21-search-service-sync-worker-extension-design.md (prerequisite) — extends search-sync-worker so the user-room ES doc carries both unrestricted (rooms []string) and restricted (restrictedRooms map[rid]hss) memberships.

    • Updates painless scripts to route by HSS.
    • Changes pkg/model.InboxMemberEvent and MemberAddEvent HistorySharedSince from int64*int64 with omitempty to disambiguate "unrestricted" from "restricted-since-epoch-0".
    • Spotlight index unchanged (still skips restricted-room events for MVP — documented gap).
  3. 2026-04-21-chat-frontend-search-design.md — the React/Vite UI consumer.

    • Top-header global search bar (Microsoft Teams-style) with debounced search-as-you-type and 5-item dropdown preview.
    • Enter opens a tabbed full-results view (Rooms paginated, Messages lazy on tab click).
    • Ctrl+F in-room scoped message search via roomIds: [selectedRoom.id].
    • Browser→NATS via existing nats.ws; new useDebounce and useSearch hooks; new subjects.searchRooms / subjects.searchMessages builders.

Brainstorming context

Designed via the superpowers:brainstorming skill across multiple iterations covering: schema gap analysis vs PR #109 indexes (collapsed to MVP-first), CCS approach (native ES wildcard alias vs client-side fan-out), restricted-room state location (ES doc vs Mongo at query time), Valkey caching, and frontend UX scope decomposition. Several MVP parity gaps are documented explicitly with post-MVP follow-ups (tshow, hidden, archived, prid, fname/sidebarname, ls sort, scope=app, push cache invalidation).

Implementation order

The three specs are independent but have a clear dependency chain. Plans will be written and executed in this order:

  1. Sync-worker extension (prerequisite — search-service can't read restrictedRooms{} until the worker writes it).
  2. Search-service.
  3. Frontend.

Test plan

  • Spec review by maintainers
  • Implementation plans drafted (one per spec) and executed in dependency order
  • CCS integration test passes locally with two ES containers
  • Restricted-room access correctly enforced under all rooms[]/restrictedRooms{} combinations

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3

Summary by CodeRabbit

Release Notes

  • Documentation
    • Added design specifications for global search functionality including real-time search-as-you-type across rooms and messages, paginated results display, and room-scoped search via keyboard shortcut for seamless chat navigation.

claude added 4 commits April 21, 2026 15:13
Context, goals, architecture, data flow, query construction, and wire schemas
for the new NATS request/reply search-service. Part 2 (file layout, config,
testing, ops) follows.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
…tension companion spec

- Appends file layout, pkg/ additions, config, error handling, observability,
  docker-local (Valkey + Kibana), testing strategy incl. CCS integration test,
  known MVP parity gaps, and decision log to the search-service spec.
- Adds the prerequisite sync-worker extension spec covering user-room
  restrictedRooms schema, painless script updates, and *int64 HistorySharedSince
  in pkg/model.InboxMemberEvent / MemberAddEvent.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
…hape

Query builder had a hardcoded 'now-1y' that contradicted the configurable
SEARCH_RECENT_WINDOW env var. Replaced with placeholder that derives from the
configured duration at runtime.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
Covers the frontend consumer of the new search-service: top-header global
search bar with debounced search-as-you-type, dropdown preview, tabbed full
results (Rooms paginated, Messages lazy), and Ctrl+F in-room message search
scoped via roomIds. Matches existing React/hook/subjects conventions.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@Joey0538 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 51 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 39 minutes and 51 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 463c1cd7-bf56-430d-8ebf-87fa416111b0

📥 Commits

Reviewing files that changed from the base of the PR and between 6f63d47 and 350e6cf.

📒 Files selected for processing (2)
  • docs/superpowers/specs/2026-04-21-search-service-design.md
  • docs/superpowers/specs/2026-04-21-search-service-sync-worker-extension-design.md
📝 Walkthrough

Walkthrough

This PR introduces three comprehensive design specifications for a chat platform search feature: a frontend global search UX consuming backend NATS endpoints, a backend search-service implementation using Elasticsearch and Valkey caching, and sync-worker extensions for managing user-room restricted access.

Changes

Cohort / File(s) Summary
Search Feature Design Specs
docs/superpowers/specs/2026-04-21-chat-frontend-search-design.md, docs/superpowers/specs/2026-04-21-search-service-design.md, docs/superpowers/specs/2026-04-21-search-service-sync-worker-extension-design.md
Three design specifications for global search: frontend UX with debounced header search bar and modal results, backend NATS request/reply service with Elasticsearch queries and access control, and sync-worker extensions including data model changes to support restricted room tracking via nullable HistorySharedSince pointers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Suggested reviewers

  • mliu33
  • yenta

Poem

🐰 Hops through specs with glee and might,
Search design docs, oh what a sight!
Front and back, sync-workers aligned,
Global queries, access defined,
Elasticsearch dancing with Valkey so bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: adding three design specification documents for a search-service system covering backend, sync-worker, and frontend components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/search-service-nats-HQVRk

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@docs/superpowers/specs/2026-04-21-search-service-sync-worker-extension-design.md`:
- Line 35: Update the spec to resolve the *int64 vs painless sentinel ambiguity
by either (A) documenting in the Behavioral Properties that HistorySharedSince =
&0 is canonically treated as unrestricted and publishers must not emit &0 for
genuinely restricted rooms (reference HistorySharedSince and the Behavioral
Properties section), or (B) change the decision note for HistorySharedSince to
state explicitly that the disambiguation only exists at the Go layer and the
painless translation intentionally maps nil and &0 to hss = 0 (reference the
painless script mapping of hss). Pick one option and update both the decision
table entry for HistorySharedSince and the related painless translation
discussion (lines around the hss mapping) so the spec and examples are
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d0bdc56c-0232-4710-96fa-6a51c434b7c6

📥 Commits

Reviewing files that changed from the base of the PR and between ef63c33 and 6f63d47.

📒 Files selected for processing (3)
  • docs/superpowers/specs/2026-04-21-chat-frontend-search-design.md
  • docs/superpowers/specs/2026-04-21-search-service-design.md
  • docs/superpowers/specs/2026-04-21-search-service-sync-worker-extension-design.md

Comment thread docs/superpowers/specs/2026-04-21-search-service-sync-worker-extension-design.md Outdated
Addresses CodeRabbit feedback on PR #114:
- Expand the HistorySharedSince decision rationale to state the Go-layer
  disambiguation does NOT carry through to painless (both nil and &0 map to
  hss=0).
- Add a 5th Behavioral Property codifying the publisher contract: emit nil for
  unrestricted, never &0 or a non-positive timestamp.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
claude added 2 commits April 22, 2026 04:58
PR #115 implements tshow indexing as part of the sync-worker prerequisite work.
Update both specs to reflect:

- sync-worker-ext spec: add tshow to goals; add pkg/model.Message +
  MessageSearchIndex field additions; add messages_test.go + model_test.go
  test cases covering round-trip true and omitempty behavior.
- search-service spec: drop tshow from non-goals; restore Clause B1
  (tshow=true) in the restricted-room per-room thread-reply branch; remove
  tshow from MVP parity gaps; update decision log to note the targeted
  exception.

Restricted-user thread-reply parity now matches the old Rocket.Chat semantic.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
PR #115 discovered that message-worker/store_cassandra.go was not binding the
tshow column in SaveMessage or SaveThreadMessage, even though the column
already existed in the DDL and UDT struct. Without this fix the tshow value
is always persisted as NULL, which breaks the downstream ES index population
and defeats the Clause B1 restricted-room query branch.

Spec updates:
- Goal #5 expanded to call out the message-worker binding fix.
- New "message-worker/store_cassandra.go — bind tshow in inserts" section with
  the three concrete INSERT rewrites and integration test coverage.

No DDL or UDT struct change — the column was already declared.

https://claude.ai/code/session_01JbAWPnNedoBwQL3usoPtS3
Joey0538 pushed a commit that referenced this pull request Apr 22, 2026
…ictedRooms map

Extends the user-room ES doc with a `restrictedRooms` map (rid → historySharedSince
millis) alongside the existing `rooms[]`, so search-service can enforce
restricted-room history windows directly from ES without a query-time
MongoDB lookup.

- `pkg/model.InboxMemberEvent` / `MemberAddEvent`: `HistorySharedSince`
  changes from `int64` to `*int64` with `omitempty` to disambiguate
  "unrestricted" (nil) from "restricted-since-timestamp". Publishers must
  emit nil for unrestricted rooms — the Go↔painless sentinel treats any
  `hss <= 0` as unrestricted.
- `search-sync-worker/user_room.go`: add-script routes by `params.hss`;
  remove-script evicts from both `rooms[]` and `restrictedRooms{}`.
  Template gains `restrictedRooms` as `flattened`.
- `search-sync-worker/spotlight.go`: MVP skip lifted from `!= 0` to
  `!= nil` — spotlight still does not index restricted rooms.
- `room-worker`: publisher builds `*int64` from `req.Timestamp` only when
  `History.Mode == None`.
- `inbox-worker`: handler checks `!= nil` before dereferencing.
- Tests: model round-trip covers nil/non-nil wire shape; publisher tests
  assert pointer propagation and wire-omission; integration test updated
  to expect restricted bulk lands in `restrictedRooms{}` instead of no-op.

Prerequisite for PR #114 (search-service). No behavior change for
unrestricted rooms.

https://claude.ai/code/session_018uJCyUSaHiPnmnyfUDeQUj
Copy link
Copy Markdown
Collaborator

@mliu33 mliu33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

Comment thread docs/superpowers/specs/2026-04-21-search-service-design.md
@mliu33 mliu33 merged commit a5a8a1a into main Apr 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants