feat(search): gate advanced filters
This commit is contained in:
@@ -49,11 +49,11 @@ Hermes task landing checklist:
|
||||
|
||||
## Current Baseline
|
||||
|
||||
- Current tracking checkpoint: 2026-06-07 P3.78 search message recency parity, prepared as `feat(search): scope message recency`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(search): scope message recency`.
|
||||
- Latest documentation/tooling checkpoint: this tracker update records Chatwoot SearchService `message_base_query` recency parity for global/entity message search. No route artifacts change.
|
||||
- Current tracking checkpoint: 2026-06-07 P3.79 search advanced-filter gate parity, prepared as `feat(search): gate advanced filters`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(search): gate advanced filters`.
|
||||
- Latest documentation/tooling checkpoint: this tracker update records Chatwoot SearchService `advanced_search` feature-gated filter parity for global/entity search. No route artifacts change.
|
||||
- Plan landing status: complete for the current known Hermes plans and user-confirmed scope. Future work should update this file directly instead of opening a parallel tracker.
|
||||
- Worktree status at this implementation checkpoint: reused SearchAPI global/entity message search now mirrors Chatwoot `SearchService#message_base_query` by applying a message-only `created_at >= 3.months.ago` base scope before text/filter search. DB fallback applies the scope on `messages.created_at`, Meilisearch message filters emit the same `created_at_ts` lower bound, and explicit older `since` params cannot expand message search beyond the recent base. Existing P3.77 search inbox access parity, P3.76 conversation filter query message-type parity, P3.75 automation message filter parity, P3.74 contact type default parity, P3.73 conversation filter permission parity, P3.72 account enabled-feature serialization parity, P3.71 contact referer filter parity, P5.8c contact import search indexing, P3.70 global contact search resolved-scope parity, and prior checkpoints remain implemented. Live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack.
|
||||
- Worktree status at this implementation checkpoint: reused SearchAPI advanced filters now follow Chatwoot `SearchService` feature gates: `since/until` date filters for conversations, messages, contacts, and articles apply only when account `advanced_search` is enabled; message `from` and explicit `inbox_id` filters also require `advanced_search`, while always-on message recency and current-user inbox access remain enforced. Existing P3.78 search message recency parity, P3.77 search inbox access parity, P3.76 conversation filter query message-type parity, P3.75 automation message filter parity, P3.74 contact type default parity, P3.73 conversation filter permission parity, P3.72 account enabled-feature serialization parity, P3.71 contact referer filter parity, P5.8c contact import search indexing, P3.70 global contact search resolved-scope parity, and prior checkpoints remain implemented. Live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack.
|
||||
- Next executable implementation checkpoint: continue Phase 2/3 drift audit for the next reused-frontend mismatch, or run B12 live smoke when the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack is available. Re-run Phase 6 placeholder audit after future route/smoke changes.
|
||||
- `go test ./...` passes when run outside the restricted socket sandbox for the latest implementation baseline; the latest docs/tooling checkpoint verified `scripts/parity_frontend_smoke.sh --check` with workspace-local temp/cache dirs after `/tmp` was full.
|
||||
- Route dump succeeds with `967` registered routes after profile MFA route tracking.
|
||||
@@ -156,6 +156,7 @@ This table is the shortest authoritative handoff view. If an older lower section
|
||||
|
||||
| Priority | Workstream | Current state | Next checkpoint | Commit close rule |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 0 | P3.79 search advanced-filter gate parity | Implemented for reused SearchAPI filters: GoChat now mirrors Chatwoot `SearchService` by applying `since/until`, message `from`, and message explicit `inbox_id` filters only when account `advanced_search` is enabled. Always-on message recency and user inbox access scopes remain active regardless of the feature gate. DB fallback and Meilisearch filters use the same gate. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for global `ChatwootApp.advanced_search_allowed?` gating, Searchkick advanced message filters, exact `cap_until_time` future bounds, or custom-role search visibility. | Focused search service, Meilisearch engine, and SearchRepo advanced-gate tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| 0 | P3.78 search message recency parity | Implemented for reused global/entity message search: GoChat now applies Chatwoot `SearchService#message_base_query`'s recent-message base relation (`created_at >= 3.months.ago`) before message content search and filters. The DB fallback uses `messages.created_at`; Meilisearch message searches add the same `created_at_ts` lower bound, while contact/conversation/article search remains unaffected. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for exact Rails `3.months.ago` calendar edge cases, `cap_until_time` future bounds, or advanced-search feature-gated date filter drift. | Focused search service, Meilisearch engine, and SearchRepo message-recency tests, full `go test ./...`, and `git diff --check` must pass. No route artifacts change. |
|
||||
| 0 | P3.77 search inbox access parity | Implemented for reused global/entity search: GoChat now mirrors Chatwoot `SearchService` by scoping conversation and message search to the current user's assigned inboxes unless the account user is an administrator or assigned to every inbox. The same access filter is applied to DB fallback and Meilisearch filters; inaccessible explicit `inbox_id` params are ignored so the base accessible relation is preserved like the reference. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for custom-role search visibility, exact `advanced_search` feature-gated filters, or 90-day message base-query drift. | Focused search handler, search service, Meilisearch engine, and SearchRepo access/filter tests, full `go test ./...`, and `git diff --check` must pass. No route artifacts change. |
|
||||
| 0 | P3.76 conversation filter query message-type parity | Implemented for reused conversation filter/list query flows: `q` message search now filters against persisted GoChat string message types (`incoming`, `outgoing`) while preserving the Chatwoot reference restriction to incoming/outgoing messages and excluding activity/template matches. | Keep in Review; reopen from B12 conversation search/filter smoke or fresh reference evidence for duplicate join count behavior, `processed_message_content` query drift, or exact PostgreSQL ILIKE collation differences. | Focused conversation service query filter test, full `go test ./...`, and `git diff --check` must pass. No route artifacts change. |
|
||||
@@ -242,6 +243,7 @@ These rows are the executable development plan from this point forward. A checkp
|
||||
|
||||
| ID | Owner files | Reference files | Work to land | Exit gate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| P3.79 search advanced-filter gate parity | `internal/search/search_filter.go`, `internal/search/search_service.go`, `internal/search/engine_meili.go`, `internal/repository/search_repo.go`, search service/engine/repository tests | `reference/chatwoot/app/services/search_service.rb#filter_conversations`, `reference/chatwoot/app/services/search_service.rb#apply_message_filters`, `reference/chatwoot/app/services/search_service.rb#apply_time_filter`, `reference/chatwoot/app/services/search_service.rb#apply_sender_filter`, `reference/chatwoot/app/services/search_service.rb#apply_inbox_id_filter`, `reference/chatwoot/app/javascript/dashboard/api/search.js`, `reference/chatwoot/app/javascript/dashboard/api/specs/search.spec.js` | Search filters now honor the same `current_account.feature_enabled?('advanced_search')` gates as Chatwoot: the search service resolves the account feature into the filter; DB fallback skips `since/until` date filters unless advanced search is enabled; message sender (`from`) and explicit `inbox_id` filters are ignored unless advanced search is enabled; Meilisearch omits those advanced filter expressions under the same gate. Message `created_at >= 3.months.ago` and user inbox access scopes remain always-on. | Review by `feat(search): gate advanced filters`; focused tests cover service feature propagation, DB sender filter ignored/enforced by feature state, and Meilisearch omission/emission of sender/date/inbox advanced filters; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| P3.78 search message recency parity | `internal/search/search_filter.go`, `internal/search/search_service.go`, `internal/search/engine_meili.go`, `internal/repository/search_repo.go`, search service/engine/repository tests | `reference/chatwoot/app/services/search_service.rb#message_base_query`, `reference/chatwoot/app/services/search_service.rb#filter_messages_with_like`, `reference/chatwoot/app/services/search_service.rb#filter_messages_with_gin`, `reference/chatwoot/app/javascript/dashboard/api/search.js`, `reference/chatwoot/app/javascript/dashboard/api/specs/search.spec.js` | Global/entity message search now follows Chatwoot's recent-message base relation: the search service stamps message search filters with a `3.months.ago` lower bound, DB fallback applies it to `messages.created_at` before content/filter/date predicates, Meilisearch message searches apply `created_at_ts >= cutoff`, and older explicit `since` params cannot expand the message result set beyond the reference base query. | Review by `feat(search): scope message recency`; focused tests cover service cutoff stamping, DB exclusion of older messages, and Meilisearch message filter emission; full `go test ./...` and `git diff --check` must pass. No route artifacts change. |
|
||||
| P3.77 search inbox access parity | `internal/handler/api/v1/search_handler.go`, `internal/search/search_filter.go`, `internal/search/search_service.go`, `internal/search/engine_meili.go`, `internal/repository/search_repo.go`, search handler/service/engine/repository tests | `reference/chatwoot/app/controllers/api/v1/accounts/search_controller.rb`, `reference/chatwoot/app/services/search_service.rb`, `reference/chatwoot/app/javascript/dashboard/api/search.js`, `reference/chatwoot/app/javascript/dashboard/api/specs/search.spec.js` | Global/entity search now follows Chatwoot `SearchService#message_base_query` and `#filter_conversations` inbox visibility boundaries for reused SearchAPI callers: current user id is captured from request context, account search access is resolved from `account_users`, `inbox_members`, and account inbox count, agents are restricted to assigned inboxes, administrators and agents assigned to all inboxes skip inbox filtering, DB and Meilisearch conversation/message searches apply the same accessible inbox set, and unauthorized explicit `inbox_id` filters are ignored rather than emptying the accessible base relation. | Review by `feat(search): scope inbox search access`; focused tests cover handler current-user propagation, service access injection, Meilisearch inbox filters and unauthorized inbox param fallback, SearchRepo access resolution for agents/admins/all-inbox agents, DB message search restriction, and inaccessible inbox param fallback; full `go test ./...` and `git diff --check` must pass. No route artifacts change. |
|
||||
| P3.76 conversation filter query message-type parity | `internal/service/conversation_service.go`, `internal/service/conversation_service_test.go` | `reference/chatwoot/app/finders/conversation_finder.rb#filter_by_query`, `reference/chatwoot/app/models/message.rb`, `internal/model/enums.go`, `internal/repository/conversation_repo.go` | Conversation service `Filter` query search now follows the same incoming/outgoing restriction as Chatwoot `ConversationFinder#filter_by_query`, but uses GoChat's persisted message type strings instead of raw Chatwoot enum integers. The query also uses a dialect-aware content predicate so SQLite focused tests exercise the same matching path while PostgreSQL keeps `ILIKE`. | Review by `feat(conversations): align filter query message types`; focused service test proves `q` matches incoming message content, excludes activity-only conversations, and ignores non-matching content; full `go test ./...` and `git diff --check` must pass. No route artifacts change. |
|
||||
@@ -2694,3 +2696,4 @@ Verification milestone gates:
|
||||
- 2026-06-07: P3.76 conversation filter query message-type checkpoint prepared as `feat(conversations): align filter query message types`; audited Chatwoot `ConversationFinder#filter_by_query`, message enum behavior, and GoChat persisted message type storage. GoChat conversation filter `q` searches now keep the Chatwoot incoming/outgoing-only restriction while comparing against local string message types instead of numeric enum values, so activity/template messages remain excluded and valid incoming/outgoing content is found. Focused conversation service query-filter test passed; full `go test ./...` and `git diff --check` passed. No route artifacts change.
|
||||
- 2026-06-07: P3.77 search inbox access checkpoint prepared as `feat(search): scope inbox search access`; audited Chatwoot `SearchController`, `SearchService`, and reused dashboard SearchAPI callers. GoChat global/entity conversation and message search now propagates the current user, resolves accessible inboxes from account membership and inbox assignments, scopes DB fallback and Meilisearch filters for non-admin agents, skips the scope for administrators and all-inbox agents, and ignores inaccessible explicit `inbox_id` params by preserving the accessible base relation. Focused search handler/service/engine/repository tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
- 2026-06-07: P3.78 search message recency checkpoint prepared as `feat(search): scope message recency`; audited Chatwoot `SearchService#message_base_query`, message search SQL/GIN branches, and reused dashboard SearchAPI callers. GoChat global/entity message search now stamps message filters with the Chatwoot `3.months.ago` lower bound, applies it to DB fallback `messages.created_at`, emits the same `created_at_ts` lower bound for Meilisearch message searches, and keeps the recent base relation even when older `since` params are provided. Focused search service/engine/repository tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
- 2026-06-07: P3.79 search advanced-filter gate checkpoint prepared as `feat(search): gate advanced filters`; audited Chatwoot `SearchService` feature gates around conversation/contact/article time filters and message time/sender/inbox filters, plus reused dashboard SearchAPI callers. GoChat search now resolves account `advanced_search` into the search filter, skips `since/until` date predicates unless that feature is enabled, and ignores message `from` plus explicit `inbox_id` filters unless advanced search is enabled; message recency and user inbox access remain always-on. Focused search service/engine/repository tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
|
||||
Reference in New Issue
Block a user