# 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.
