# Общая архитектура ## Tech stack | Слой | Технология | Назначение | | ------ | ----------- | ------------ | | Backend | Fastify + TypeScript | REST API сервер | | ORM | Drizzle ORM | Типизированный доступ к БД | | Database | PostgreSQL | Основное хранилище | | Cache | Redis | Кэш вопросов, сессии, rate limiting | | Frontend | React + TypeScript + Vite | SPA клиент | | LLM | Локальный LLM (dev), облачный API (prod) | Генерация вопросов | | Логирование | Pino | Структурированные JSON-логи | | Мониторинг ошибок | Sentry | Отлов ошибок в production | | Deploy | VPS + Docker Compose | Хостинг | ## Схема взаимодействия ```mermaid flowchart TB Browser["Browser (React SPA)"] API["Fastify API"] DB["PostgreSQL"] Cache["Redis"] LLM["LLM Service"] LocalLLM["Local LLM (dev)"] CloudLLM["Cloud API (prod)"] Browser -->|"HTTP/JSON"| API API --> DB API --> Cache API --> LLM LLM --> LocalLLM LLM --> CloudLLM ``` ## Структура репозиториев ```text samreshu-backend Fastify + TS + Drizzle samreshu-frontend React + TS + Vite samreshu-docs Документация, ADR, прогресс ``` Общие типы хранятся в каждом репо отдельно — без отдельного shared-пакета. ## Архитектурные принципы Принципы, не обсуждаемые при написании любого кода: ### 1. Подписка читается из БД через middleware `user.plan` всегда определяется через subscription middleware. Права никогда не хардкодятся в контроллерах. ### 2. Снепшот вопросов при старте теста Вопросы копируются в `test_questions` при создании теста. Во время прохождения теста `question_bank` никогда не читается напрямую. ### 3. LLM-вызовы только через LlmService Остальной код не знает, какая модель работает. Провайдер, URL и ключ задаются через переменные окружения. ### 4. Валидация внешних данных по JSON-схеме Все внешние события (webhooks, ответы LLM) валидируются. Внешним данным не доверяем без проверки. ### 5. Проверки прав и лимитов только на backend Frontend только отображает состояние. Все авторизационные решения принимаются на сервере. ### 6. Все даты в UTC Хранение и передача дат — UTC. Конвертация в часовой пояс пользователя только на фронте. ### 7. Конфигурация через переменные окружения Никаких хардкодов. Все настройки (БД, Redis, LLM, ключи) читаются из `.env`.