first commit
This commit is contained in:
126
memory_bank/architecture.md
Normal file
126
memory_bank/architecture.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Архитектура
|
||||
|
||||
## Общий подход
|
||||
|
||||
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;
|
||||
- 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 — детерминированный оптимизатор с весовой функцией качества и ограниченным поиском вариантов. Алгоритм располагается в доменном слое и не зависит от БД. Позже его можно заменить на constraint 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 и внешние резервные копии;
|
||||
- адаптивность от мобильного экрана до большого дисплея.
|
||||
Reference in New Issue
Block a user