Problem
The integration suite calls a second implementation of core HTTP endpoints, not the routers and services shipped by the server. It can therefore remain green if a production handler is deleted, its validation changes, or its persistence effects break.
Evidence
createTestApp explicitly says its routes are "simplified versions" at tests/integration/setup.ts:42-43; the relationship handler states it intentionally diverges from production at lines 160-164. The test harness reimplements search at lines 298-331 and AI discovery progress/apply/apply-batch at lines 386-433. All seven API specs import this harness, including Search Routes at tests/integration/api/search.spec.ts:9-21 and AI Discovery API at tests/integration/api/ai-discovery.spec.ts:9-31. Production search instead parses the full filter/pagination request in server/src/routes/search.routes.ts:8-25 and delegates to searchService; production AI discovery has a 1,000-candidate cap and service-backed endpoints at server/src/routes/ai-discovery.routes.ts:10-16, 23-62, 106-141, neither of which the lookalike tests execute.
Impact
CI currently reports API coverage while missing regressions in route registration, request parsing, error middleware, ID resolution, service interaction, and production-only safeguards. In particular, a no-op or replaced production search/AI route would not fail the named integration tests.
Implementation plan
Extract a production app factory that mounts the existing routers and accepts test-owned adapters/configuration for SQLite, files, AI discovery, and browser-dependent services; keep the executable bootstrap as the only code that binds a port. Replace the reimplemented handlers in tests/integration/setup.ts with that factory and deterministic dependency fakes at the external boundaries only. Port the database, person, relationship, favorites, search, and AI discovery specs to requests against actual routers. Seed data through the production persistence seam. Add contract matrices that assert: all search filters (q, location, occupation, birth range, generation range, hasPhoto, hasBio), invalid/negative/huge page and limit inputs, correct total/totalPages, and no cross-database results; AI quick/start service failure response, one-run conflict, apply-batch exactly at 1,000 versus 1,001, malformed candidates, and durable favorite writes. Assert observable response status/body and persisted state rather than internal helper calls.
Acceptance criteria
No test-only endpoint duplicates production business logic. The affected API specs import and exercise the production route modules through a shared app factory. Their fixtures demonstrate each stated boundary and side effect, including the 1,001-candidate rejection and a production-service failure. Removing a mounted production route or replacing a delegated service call with a no-op makes a corresponding test fail.
Verification
Run npm test -- --run, npm run test:integration, and npm run build. Perform a mutation check by temporarily removing the production search router mount, changing the production batch maximum, and bypassing the favorite write; each mutation must fail a targeted integration test before reverting it.
Dependencies and related work
Do not duplicate PostgreSQL migration coverage planned in #120 and #149-#155. This is a test-harness and active SQLite/JSON API contract change, not a database-migration issue.
Scope
Complexity: large. Files: server/src/index.ts or a new app-factory module, the existing routers/services only as needed for injection, tests/integration/setup.ts, and the affected integration specs. Non-goals: changing product endpoint semantics, browser automation behavior, or adding live external-provider calls.
Problem
The integration suite calls a second implementation of core HTTP endpoints, not the routers and services shipped by the server. It can therefore remain green if a production handler is deleted, its validation changes, or its persistence effects break.
Evidence
createTestAppexplicitly says its routes are "simplified versions" attests/integration/setup.ts:42-43; the relationship handler states it intentionally diverges from production at lines 160-164. The test harness reimplements search at lines 298-331 and AI discovery progress/apply/apply-batch at lines 386-433. All seven API specs import this harness, includingSearch Routesattests/integration/api/search.spec.ts:9-21andAI Discovery APIattests/integration/api/ai-discovery.spec.ts:9-31. Production search instead parses the full filter/pagination request inserver/src/routes/search.routes.ts:8-25and delegates tosearchService; production AI discovery has a 1,000-candidate cap and service-backed endpoints atserver/src/routes/ai-discovery.routes.ts:10-16, 23-62, 106-141, neither of which the lookalike tests execute.Impact
CI currently reports API coverage while missing regressions in route registration, request parsing, error middleware, ID resolution, service interaction, and production-only safeguards. In particular, a no-op or replaced production search/AI route would not fail the named integration tests.
Implementation plan
Extract a production app factory that mounts the existing routers and accepts test-owned adapters/configuration for SQLite, files, AI discovery, and browser-dependent services; keep the executable bootstrap as the only code that binds a port. Replace the reimplemented handlers in
tests/integration/setup.tswith that factory and deterministic dependency fakes at the external boundaries only. Port the database, person, relationship, favorites, search, and AI discovery specs to requests against actual routers. Seed data through the production persistence seam. Add contract matrices that assert: all search filters (q, location, occupation, birth range, generation range, hasPhoto, hasBio), invalid/negative/huge page and limit inputs, correct total/totalPages, and no cross-database results; AI quick/start service failure response, one-run conflict,apply-batchexactly at 1,000 versus 1,001, malformed candidates, and durable favorite writes. Assert observable response status/body and persisted state rather than internal helper calls.Acceptance criteria
No test-only endpoint duplicates production business logic. The affected API specs import and exercise the production route modules through a shared app factory. Their fixtures demonstrate each stated boundary and side effect, including the 1,001-candidate rejection and a production-service failure. Removing a mounted production route or replacing a delegated service call with a no-op makes a corresponding test fail.
Verification
Run
npm test -- --run,npm run test:integration, andnpm run build. Perform a mutation check by temporarily removing the production search router mount, changing the production batch maximum, and bypassing the favorite write; each mutation must fail a targeted integration test before reverting it.Dependencies and related work
Do not duplicate PostgreSQL migration coverage planned in #120 and #149-#155. This is a test-harness and active SQLite/JSON API contract change, not a database-migration issue.
Scope
Complexity: large. Files:
server/src/index.tsor a new app-factory module, the existing routers/services only as needed for injection,tests/integration/setup.ts, and the affected integration specs. Non-goals: changing product endpoint semantics, browser automation behavior, or adding live external-provider calls.