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

10 KiB
Raw Blame History

Архитектура

Общий подход

Backend строится на Go по принципам Clean Architecture. Зависимости направлены внутрь: инфраструктура и доставка зависят от сценариев приложения, сценарии — от доменной модели.

Backend

Предлагаемая структура:

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 группируется по продуктовым возможностям:

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 и внешние резервные копии;
  • адаптивность от мобильного экрана до большого дисплея.