# Архитектура backend ThaiForTravel Mini App

## Решение

Mini App не читает стандартный WordPress REST напрямую. На сайте устанавливается небольшой плагин `tft-miniapp-api`, который собирает разнородные CPT и ACF-поля в стабильную схему. Backend кэширует эту схему и добавляет пользовательские данные.

## Что подтвердил аудит WordPress

- Экскурсии находятся в CPT `pattaya`, `phuket`, `yacht`, `yacht_phuket` и тематических типах.
- ACF доступен в REST, но значения цен находятся в разных ветках, чаще всего в `programs.variants`.
- У экскурсии встречаются несколько вариантов программы и несколько цен.
- Трансферы являются страницами с `template-transfer.php`.
- Категории WordPress сейчас в основном обозначают направление, поэтому для Mini App добавляется отдельная таксономия.
- В ACF встречается лишняя служебная HTML-разметка. Плагин обязан очищать её и не отдавать сырые поля.

## Границы ответственности

### WordPress plugin

- знает CPT, ACF и медиатеку;
- нормализует цены, галерею, программу и включённые услуги;
- добавляет категорийную таксономию Mini App;
- кэширует нормализованный каталог transient-кэшем;
- сбрасывает кэш при изменении записи, мета или терминов.

### Mini App Backend

- проверяет Telegram initData;
- хранит пользователя, избранное, заявки, планы и напоминания;
- кэширует ответы WordPress в Redis;
- не сохраняет каталог как вторую редактируемую копию;
- создаёт неизменяемый snapshot услуги внутри заявки;
- доставляет события через transactional outbox.

### Telegram Bot

- получает уведомление о новой заявке;
- подтверждает пользователю приём заявки;
- отправляет напоминания;
- остаётся основным каналом общения после Mini App.

### CRM

- подключается через адаптер;
- получает заявку асинхронно;
- временная недоступность CRM не блокирует ответ пользователю.

## Рекомендации плана

Фильтр выполняется до ранжирования:

1. Только город выбранного плана.
2. Только услуги, подходящие по датам и длительности.
3. Исключить уже добавленные услуги.
4. Повысить совпадение выбранных категорий.
5. При наличии детей повысить семейные предложения.
6. Понизить тяжёлые активности рядом с уже насыщенным днём.

Рекомендация остаётся подсказкой. Пользователь всегда может открыть поиск по полному каталогу того же города.

## Безопасность

- Telegram HMAC и ограничение возраста initData.
- CORS только для известного origin.
- Лимит тела JSON 256 KB.
- Секретный endpoint очистки каталога.
- Секреты только через ENV.
- Персональные данные не включаются в обычные application logs.
- Запросы создания требуют `Idempotency-Key`.
- Публичные идентификаторы заявок не являются последовательными.
