Files
mixmaker/memory_bank/architecture.md
lemintare 1239fcee08
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / compose (push) Has been cancelled
Initialize project with basic structure, including Docker configuration, backend and frontend setup, environment configuration, and essential files for development.
2026-07-19 00:17:31 +03:00

130 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Архитектура
## Общий подход
Backend строится на Go по принципам Clean Architecture. Зависимости направлены внутрь: инфраструктура и доставка зависят от сценариев приложения, сценарии — от доменной модели.
## Backend
Предлагаемая структура:
```text
backend/
cmd/api/ точка входа HTTP-сервера
internal/
domain/ сущности, value objects, правила, доменные ошибки
application/
usecase/ сценарии приложения
port/ интерфейсы репозиториев, часов, генераторов, событий
adapter/
in/http/ handlers, middleware, DTO
out/postgres/ реализации репозиториев
out/realtime/ доставка событий клиентам
platform/ конфигурация, логирование, подключение инфраструктуры
migrations/
```
Технологии первой версии:
- Go;
- PostgreSQL;
- REST API для команд и запросов;
- WebSocket или Server-Sent Events для синхронизации драфта и сетки;
- Discord OAuth 2.0 для входа;
- серверная cookie-сессия с HttpOnly, Secure и SameSite;
- структурированное логирование;
- OpenAPI как контракт frontend/backend.
## Frontend
Предлагаемый стек:
- React + TypeScript;
- Vite;
- TanStack Router и TanStack Query;
- собственный типизированный слой локализации RU/EN с сохранением языка в localStorage;
- Tailwind CSS;
- shadcn/ui как основа компонентов;
- Framer Motion для умеренных анимаций;
- React Hook Form + Zod;
- dnd-kit для ручной корректировки составов;
- библиотека турнирной сетки только после проверки мобильного UX; при необходимости — собственный SVG-компонент.
Структура frontend группируется по продуктовым возможностям:
```text
frontend/src/
app/
pages/
widgets/
features/
entities/
shared/
```
## Границы модулей
- Players: профили, рейтинги, предпочтения ролей и желаемых союзников;
- Auth: Discord OAuth, сессии и роли доступа;
- Admin: управление игроками, регистрациями, событиями и капитанами;
- Events: календарь, регистрации участников и состояние игрового вечера;
- Balancing: генерация и оценка составов;
- Draft: жеребьёвка, карты и герои;
- Matches: карты, счёт и завершение серии;
- Tournaments: сетка и продвижение команд;
- Realtime: подписка клиентов на изменения.
## Ключевые решения
### Балансировщик
В MVP — детерминированный оптимизатор с весовой функцией качества и ограниченным поиском вариантов. Overwatch-ранги Bronze 5 → Champion 1 отображаются в ordinal 140 только для внутренних вычислений. Жёсткие ограничения обеспечивают состав 1/2/2 и уникальность игроков. Мягкие штрафы учитывают общий и ролевой разброс рейтинга, назначение вне предпочитаемой роли и разделение желаемых союзников. После построения нескольких начальных вариантов выполняется локальный поиск обменами игроков одной роли.
Алгоритм располагается в доменном слое и не зависит от БД. При росте сообщества его можно заменить на CP-SAT/MILP solver без изменения API сценария.
### Драфт как конечный автомат
Жеребьёвка и баны моделируются состояниями и допустимыми командами. Сервер является источником истины и отклоняет действие, если оно нарушает порядок или регламент.
### История действий
Все действия драфта сохраняются как неизменяемые записи аудита. Текущее состояние можно хранить в обычных таблицах; полноценный Event Sourcing для MVP не требуется.
### Авторизация
Вход выполняется через Discord OAuth 2.0. После callback backend создаёт собственную серверную сессию и безопасную HttpOnly-cookie; OAuth-токен Discord не передаётся frontend. Discord ID является внешним идентификатором аккаунта.
Глобальные роли MVP — Admin и Player; Captain назначается Admin для конкретной команды, а read-only spectator-доступ доступен авторизованным игрокам. Игрок редактирует только собственный профиль, рейтинги и RSVP. Admin управляет событиями, может изменить RSVP за игрока, подтверждает участников, назначает капитанов и фиксирует результаты. Начальные Admin задаются через `ADMIN_DISCORD_IDS`, чтобы роль нельзя было получить через публичный интерфейс.
### Календарь и участие
События хранятся в UTC и отображаются в локальном часовом поясе пользователя. REST API отдаёт будущие события и статусы Going/Maybe/NotGoing. Изменения регистрации публикуются через realtime-канал, чтобы Admin сразу видел актуальный список. При изменении статуса за другого игрока API сохраняет actor ID и источник `admin`, а UI показывает, кем сделана отметка.
### Капитаны
Капитан — назначение внутри конкретной команды, а не глобальная роль аккаунта. Admin может назначить или заменить капитана только участником этой команды. Только текущий капитан выполняет командные действия драфта; Admin имеет аварийное право выполнить действие с обязательной записью в аудит.
### Результаты матчей
Исход каждой карты фиксируется отдельной командой use case. Домен серии пересчитывает счёт и победителя, а турнир продвигает победившую команду только после завершения серии. Исправление результата не удаляет историю первоначального действия.
### Развёртывание в Coolify
Production разворачивается из репозитория как один Docker Compose resource: frontend/reverse proxy, Go API, миграции и PostgreSQL с named volume. Coolify сам создаёт сеть стека и подключает свой proxy, поэтому в Compose не объявляются `networks`, `container_name` и вручную заданные Traefik labels.
Frontend-контейнер обслуживает SPA и проксирует `/api` и SSE к сервису `api`, поэтому приложению достаточно одного публичного домена. PostgreSQL и API не публикуют host-порты; сервисы обращаются друг к другу по Compose-именам. Секреты и production-переменные задаются в Coolify UI, а в репозитории хранится только `.env.example`.
Для всех долгоживущих сервисов задаются healthcheck и корректный graceful shutdown. Данные PostgreSQL сохраняются в named volume; для production обязательно настраивается регулярный backup тома/БД вне сервера.
## Нефункциональные требования
- идемпотентность команд, которые могут повториться из-за сети;
- optimistic UI только там, где возможен безопасный откат;
- серверная валидация всех правил;
- миграции схемы БД;
- unit-тесты доменных правил и балансировки;
- интеграционные тесты репозиториев и API;
- production Docker Compose совместим с Coolify без пользовательских сетей;
- PostgreSQL имеет persistent volume, healthcheck и внешние резервные копии;
- адаптивность от мобильного экрана до большого дисплея.