# Fase 4 — what has been built

- `supabase/migrations/010_search_vectors.sql` — STORED GENERATED `search tsvector` columns on `shopping_items`/`tasks`/`notes` + GIN indexes + `search_result_type` enum + `search_in_collective(p_collective_id, p_query, p_types, p_creator, p_from, p_to)` SECURITY INVOKER function (RLS-aware, trash-excluded) + GRANT EXECUTE to anon/authenticated. Config is `simple` (no stemmer — bilingual en/es).
- `apps/web/src/lib/stores/search.ts` — RPC wrapper with `SearchRow` + `SearchFilters` types
- `/search` route — debounced input (300ms, ≥2 chars), filter chips (Lists/Tasks/Notes; all-active = no filter sent), results grouped by type with `data-testid="search-group-<type>"`, deep-link to the right route per result type
- `apps/web/messages/{en,es}.json` — search strings (`search_filter_*`, `search_group_*`, `search_empty`, `search_hint`)
- pgTAP `007_search_tsvector.sql` (9 tests: columns, GIN indexes, function signature, generated-vector invariant)
- Vitest `search.test.ts` (10 tests across S-01..S-04) + `rls-audit.test.ts` (42 tests: 3 intruders × 14 cross-collective ops — proves zero leakage across every domain table)
- Playwright `search.test.ts` (2 tests: SR-01 happy-path, SR-02 filter deactivation)
