## Exploration: MySQL persistence for ActivePiece reviews

### Current State
The webhook currently receives review data as query parameters on `POST /webhook/activepieces/review`, validates `id`, `name`, `nombre`, `comentario`, and `puntuacion`, then passes a normalized `ReviewInput` into `ReviewResponseService` to generate a Spanish reply. There is no database layer, no MySQL dependency, and no persistence path.

### Affected Areas
- `src/routes/reviewRoute.ts` — current webhook entrypoint and validation/mapping.
- `src/services/reviewResponseService.ts` — review payload contract that will need extra fields for persistence.
- `src/server/app.ts` — composition root where a persistence service/repository can be injected.
- `src/config.ts` — needs DB env parsing/validation (`DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`, `DB_PORT`).
- `package.json` — add MySQL driver dependency and possibly types if needed.
- `src/routes/reviewRoute.test.ts` and service tests — update for new persistence behavior and idempotency checks.

### Approaches
1. **Route-level persistence with a MySQL repository** — keep the webhook route as the integration point, but inject a small repository/service that upserts into `reviews` before/after reply generation.
   - Pros: minimal architectural change, easy to test with mocks, fits current Express composition.
   - Cons: route may become orchestration-heavy if not split carefully.
   - Effort: Medium

2. **Dedicated review ingestion service** — extract payload normalization + persistence + response generation into a single application service used by the route.
   - Pros: cleaner boundaries, easier to reuse for future sources, better place for idempotency logic.
   - Cons: more refactor work, more files to update.
   - Effort: Medium/High

### Recommendation
Use a dedicated persistence repository plus a thin orchestration service, wired from `app.ts`. This preserves the current Express shape while keeping SQL and upsert logic out of the route. The service should upsert by `review_id` and then call the existing Gemini responder.

### Risks
- Incoming payload shape may not directly match the target table, especially `author_profile_url`, `author_url`, `images`, and timestamps.
- Duplicate deliveries will require deterministic upsert behavior on `review_id`.
- Secrets must stay in environment variables only; do not hardcode database credentials anywhere.

### Ready for Proposal
Yes — the codebase structure is clear enough to draft a proposal and implementation plan.
