# Implementer — F-012 Search: interface plus PostgreSQL FTS ## Summary Implemented catalog search behind a dedicated search port with a PostgreSQL full-text search adapter, stable relevance ordering, pagination, brand filtering, and structured search telemetry. ## Code changes - Split search from product persistence: - `ProductSearchCriteria` in `project/src/modules/catalog/domain/product.ts`. - `ProductSearchRepository` in `project/src/modules/catalog/domain/ports.ts`. - `SearchProducts` now depends on `ProductSearchRepository`, not `ProductRepository`. - Added PostgreSQL FTS implementation: - `project/src/modules/catalog/infrastructure/pg-product-search-repository.ts`. - Searches product name/description/SEO fields, brand fields, and category fields. - Uses `websearch_to_tsquery('spanish', q)` and `ts_rank_cd`. - Stable ordering: rank DESC for query search, then `created_at DESC`, `name ASC`, `id ASC`; non-query listing uses `created_at DESC`, `name ASC`, `id ASC`. - Preserves active-only public search, brand slug filtering, limit, and offset. - Added FTS indexes: - `project/migrations/010_catalog_search_fts.js`. - Added search telemetry: - `GET /products/search` measures duration with `performance.now()`. - Logs structured `catalog_search` events via the existing app logger with query presence, bounded sanitized query, brand slug, pagination, duration, and result count. - Query telemetry redacts email-like values, Stripe-like keys, and long token-like strings before logging. - Composition root passes the app logger into catalog routes. - Updated unit tests: - `project/src/modules/catalog/tests/product-use-cases.test.ts` verifies search defaults/active-only forwarding through the dedicated port. ## Evidence - `cd project && npm run lint` — PASS. - `cd project && npm run typecheck` — PASS. - `cd project && npm test` — PASS: 17 files passed, 7 skipped; 64 passed, 33 skipped. - `./scripts/verify.sh` — PASS. - Security correction run: telemetry query sanitization added, then lint/typecheck/test/verify rerun and passed. ## Notes - No new npm dependencies. - No Elasticsearch/Meilisearch/Algolia, no typo-tolerance layer, no suggestions UI, no Redis/cache persistence. - Integration tests remain skipped without `TEST_DATABASE_URL`, consistent with prior features.