1. Миссия и продуктовая концепция
Миссия SUPER CUBE Games — сделать небольшие независимые игры доступными сразу после открытия ссылки, без установки клиента и лишних шагов. Платформа — не просто список HTML-файлов: она обеспечивает публикационный процесс, каталогизацию, безопасный запуск игр, аккаунты, сохранения, измеримые данные об использовании.
Пользователи и их потребности
- Игрок: быстро найти игру, запустить её на любом экране, вернуться к прогрессу, увидеть мнение сообщества и управлять профилем.
- Администратор/издатель: загрузить архив, проверить закрытую сборку, отредактировать карточку, опубликовать игру, оценить качество и популярность, управлять аккаунтами игроков.
- Разработчик: получить предсказуемый формат ZIP, небольшой асинхронный SDK, понятные ограничения среды и проверяемый путь от локальной сборки к публикации.
Продуктовые принципы
- Instant play: каталог — главный вход в игры, карточка игры даёт контекст, явная кнопка «Играть» начинает запуск.
- Progressive complexity: простая браузерная игра не требует собственного backend; серверная логика включается только при необходимости.
- Server-authoritative data: сервер определяет сохранённый прогресс, длительность сессии, рейтинги, отзывы и очки.
- Mobile-first: контролы должны работать с мышью, клавиатурой и touch; содержимое не должно превышать доступную высоту игрового окна без необходимости.
- Observable by design: ключевые игровые действия и пользовательские потоки должны иметь метрики, которые можно диагностировать.
2. Scope и критерии успеха
Входит в MVP
- Административный вход настраивается через
ADMIN_LOGIN,ADMIN_PASSWORDиADMIN_EMAIL. - Публичный каталог, поиск/фильтры и карточка-попап игры; fullscreen-страница запуска с хэдером и кнопкой назад.
- Загрузка ZIP до 100 MiB, проверка структуры, безопасная распаковка, приватный тест, редактирование RU/EN данных и публикация.
- Browser iframe runtime и Docker runtime для игр с серверным кодом.
- Вход по email-коду через SMTP.
- Оценки, множественные комментарии, ответы администратора, избранное, шаринг, облачные сохранения и профиль игрока.
- Серверный рейтинг очков, админ-панель со статистикой, история CCU и дневной аудитории, SEO endpoints.
Вне scope текущего MVP
- Мультисерверная оркестрация серверных игр и автоматическое горизонтальное масштабирование.
- Полноценная защита от DDoS на сетевом уровне, античит уровня коммерческих рейтинговых соревнований и ручная модерация большого пользовательского каталога.
- Гарантированная сохранность внутриигровой оперативной памяти сервера после аварии; постоянное игровое состояние должно храниться в БД или другом долговечном хранилище.
Измеримые признаки успешного выпуска
Критический пользовательский сценарий должен проходить end-to-end: загрузка архива → приватный preview → редактирование → публикация → доступность каталога → запуск → серверные события/время → статистика и профиль. Отдельные проверки подтверждают изоляцию черновиков, корректность ролей и отказ небезопасным запросам.
3. Системная архитектура
Browser / mobile browser
├─ Public UI: catalogue, game modal, fullscreen player, profile, leaderboard
├─ Admin UI: upload/editor, recommendations, metrics dashboards
└─ Game iframe (sandbox, no allow-same-origin)
│ postMessage SDK bridge
▼
Node.js 20+ / Express — Platform API (:3000)
├─ Auth + business rules + CSRF / Origin / rate limits
├─ Catalog + archive pipeline + private file serving
├─ SDK bridge + review/rating/favourite/save/share APIs
└─ Analytics / score calculation / snapshot scheduler
│ private HTTPS/HTTP + Bearer service token
▼
Data API (:4001, internal only; registered SQL allowlist)
│ node-postgres pool
▼
PostgreSQL 16 (users, games, sessions, reviews, saves, analytics)
Persistent volume: storage/games, storage/avatars, uploaded archives
Separate per-game Docker runtime remains an infrastructure integration
Основные модули
server.js— HTTP-маршруты, middleware, страницы игр, SDK bridge, admin APIs, ping endpoint, периодические snapshots.src/db.js— совместимый клиент внутреннего Data API; SQL-драйвера здесь нет.shared/data-client.jsиshared/data-api-session-store.js— контракт Data API и PostgreSQL-backed Express sessions.data-service/server.js,data-service/schema.sql,data-service/query-catalog.json— внутренний Data API, PostgreSQL-схема и реестр разрешённых запросов.src/auth.js— email-коды и сессии аккаунтов.src/security.js— CSRF, нормализация и экранирование.src/games.js— ZIP-валидация, распаковка, metadata parsing, preview draft.src/server-game-runtime.js— Docker network/container lifecycle, readiness probe и reverse proxy.src/analytics.js— игровые события, сессии, рейтинги, очки, каталожные метрики и тренды.public/js/common.js— общие сетевые запросы, тема/язык, CSRF и bootstrap аккаунта.
4. Канонический формат ZIP
my-game.zip
├── index.html # browser client / UI
├── runtime.txt # optional: "server" for Docker runtime
├── server/
│ └── index.js # required when runtime.txt = server
└── media/
├── title.txt # required; English title only
├── description.ru.txt # required
├── description.en.txt # required
├── tags.ru.txt # required localized metadata source
├── tags.en.txt # required; English tags are displayed/filtered
├── capsule.jpg # JPG/GIF, exactly 630 × 500
├── screenshots/ # optional game screenshots
│ ├── 01.jpg
│ └── 02.webp
└── ... # other promo materials
Текст — UTF-8. title.txt должен быть английским; интерфейс показывает его одинаково при любом языке страницы. Описание берётся из текущей локали. Теги для публичного каталога, фильтров и карточки всегда берутся из tags.en.txt, чтобы категории не дублировались при смене языка. runtime.txt находится в корне ZIP и содержит только browser или server; отсутствие файла означает browser.
Архивы старого формата с корневыми title.txt, description.txt и tags.txt временно поддерживаются для обратной совместимости. Новые сборки должны использовать канонический путь media/. Лимиты: ZIP до 100 MiB; распакованные данные до 250 MB; до 2,000 файлов; ограничения на traversal, абсолютные пути, symlinks, коэффициент сжатия и размер обязательных файлов.
5. Жизненный цикл публикации
- Администратор отправляет ZIP через drag-and-drop или файловую кнопку; интерфейс показывает точный размер в байтах, KiB/KБ и MiB/МБ.
- Backend проверяет архив до и в ходе распаковки и создаёт draft со стабильным slug.
- Черновик доступен только администратору по
/games/<slug>-test; закрывается доступ как к тестовой HTML-странице, так и к ассетам. - Редактор сохраняет описание и теги RU/EN обратно в файлы
media/, обновляет число игроков и runtime type. - После публикации браузерная игра доступна на
/games/<slug>; серверная запускается/пробуждается через runtime manager. - Unpublish и delete останавливают контейнер. На старте приложения опубликованные server games проходят попытку автоматического запуска.
6. SDK и модель изоляции
SDK предоставляет window.SuperCubePlatform. В browser runtime его скрипт инжектируется в HTML. В server runtime proxy вставляет /js/game-sdk.js?slug=<slug>, если приложение не подключило SDK само. API-вызовы идут из iframe через postMessage к host-странице и затем к backend. Sandbox намеренно не имеет allow-same-origin; не добавляйте этот флаг для обхода коммуникационного контракта.
| Метод | Назначение и ограничения |
|---|---|
getUser() | Возвращает authenticated, displayName, playerId без email. |
save(data) / loadSave() | Серверное облачное сохранение до 250 KB; только авторизованным. Гость при load получает null и requiresSignIn. |
rate(1..5) | Создать/обновить одну актуальную оценку игрока для игры. |
review(text) | Создать отзыв. Поддерживается несколько отзывов; пользователь редактирует только свои, администратор удаляет и отвечает. |
favorite() | Переключить избранное; очковая награда за игру не начисляется повторно. |
share() | Регистрирует намерение поделиться игрой на сервере и возвращает URL. |
recordClick(label) / track(event,metadata) | События действий, старта/завершения уровня; сервер проверяет допустимые типы и длину label. |
Всегда обрабатывайте Promise через try/catch. Не передавайте в SDK токены, пароли, email, секреты или игровые payload большого размера. Не считайте локальный клиент авторитетным источником очков, сохранений или результатов матча.
7. Аккаунты, идентификаторы и данные
У каждого аккаунта есть внутренний numeric ID для связей базы и отдельный публичный player ID формата SC-.... Публичный лидерборд раскрывает только player ID, nickname и points. Email и внутренний идентификатор доступны администраторам по защищённому API, для аналитики и связи с игроком.
PostgreSQL хранит пользователей, игры и metadata, сессии, события, ratings, reviews/replies, favorites, cloud saves, email OTP и snapshots. Все обращения к PostgreSQL проходят через отдельный внутренний Data API; Platform API не содержит PostgreSQL-драйвер и не получает пароль БД. Файлы игр и аватары пока живут в постоянном storage/ volume. Аватарный оригинал выбирается как 512×512; клиент уменьшает до 64×64 WebP перед отправкой, сервер валидирует размеры и сохраняет маленькую производную. Неиспользуемый старый файл аватара удаляется после замены.
8. Метрики, игровое время и очки
Метрики строятся на серверных сессиях, отзывах, оценках, событиях игры и избранного. Heartbeat отправляется примерно каждые 15 секунд. Активным считается интервал, где документ видим и окно находится в фокусе; сервер принимает только ограниченный временной интервал, а не произвольное число секунд от клиента. Heartbeats прекращаются при закрытии страницы, а конец сессии отправляется keepalive-запросом.
- CCU: уникальные игроки с живой активной сессией по heartbeat примерно за последние 45 секунд.
- Daily players: уникальные идентичности аккаунтов и гостевых браузеров с игровыми сессиями по дате.
- История: минутные snapshots CCU платформы и отдельных игр; ежедневные уникальные игроки агрегируются из сессий. История CCU накапливается только с момента запуска новой версии и не может быть восстановлена задним числом.
- Админ-аналитика: пользователи, опубликованные/черновые игры, unique players, sessions, playtime, median session duration, ratings, reviews, shares, favorites и breakdown по играм/пользователям.
Очки рассчитываются только на сервере по правилам платформы: игровое активное время, качественные отзывы, добавление игр в избранное, поделиться каждой игрой не более одного раза и суммарная регулярная активность. Для одинаковой игры в избранном/шеринге повторные действия не должны давать бесконечный прирост. Самая длинная версия отзыва — источник очков за отзывы. Публичная подсказка должна совпадать с серверной формулой: 1 очко за активную минуту, +15 за полный накопленный час; за отзыв от 3 до 99 символов начисляется 10 + floor((длина − 3) / 7), от 100 символов — 25. Учитывается самый длинный корневой отзыв по игре. Избранное и первая отправка ссылки на каждую игру дают по 5 очков однократно. Время фоновой вкладки не учитывается; очки не являются денежным балансом.
CCU и heartbeat — полезная телеметрия, но не криптографическое доказательство, что реальный человек смотрит на экран. Для соревнований с призами потребуется усиление антибота, выявление аномалий, контроль нескольких сессий и независимый аудит событий.
9. Безопасность и модель угроз
- Web requests: CSRF token на state-changing API, Origin validation, security headers, rate limiting и лимиты размера тела.
- Authentication: hash OTP с expiry/attempt limits, secrets только в серверном окружении.
- ZIP: проверка абсолютных путей,
.., symlinks, количества файлов, распакованного размера и чрезмерной компрессии; пользовательский код не выполняется процессом платформы. - Browser games: iframe sandbox without allow-same-origin; черновые страницы и ассеты защищены ролью и короткоживущим подписанным cookie.
- Server games: контейнер на игру, отдельная internal Docker network, read-only mount, non-root UID, drop capabilities, no-new-privileges, CPU/RAM/PID limits, tmpfs и отключённая внешняя сеть. Внешние user data и сохранения нужно хранить через backend/поддерживаемую БД, а не полагаться на ephemeral filesystem.
- Network edge: app-level rate limit не заменяет CDN/WAF, защиту L3/L4, reverse proxy лимиты и мониторинг сетевой нагрузки.
10. Интеграции
SMTP / email OTP
Почтовый transport задаётся через SMTP-переменные. Одноразовый код краткоживущий, сохраняется только хэш, число неверных попыток ограничено. Возврат OTP в интерфейс допустим только в development, но не в production.
Docker runtime
Каждая server game слушает 0.0.0.0:3000 внутри своего контейнера. Runtime manager отображает контейнерный порт 3000 на уникальный свободный порт хоста, доступный только через loopback-прокси платформы. Поэтому порт приложения платформы 3000 и внутренний порт игры 3000 не конфликтуют. Доступная из платформы задержка измеряется ping endpoint и показывается для серверных игр.
11. UX, локализация и доступность
- Единые theme/language настройки хранятся в
localStorage, поэтому переход по страницам их сохраняет. - Публичные UI страницы имеют RU/EN переводы. Страницы документации и SDK переводятся на русский и английский языки.
- Названия игр всегда английские; описания локализованы; пользовательские теги видны/фильтруются только на английском.
- Кнопка Play на карточке сразу запускает игру; клик по капсуле/остальной карточке открывает модал с описанием, рейтингом, отзывами и скриншотами из
media/screenshots/. - Анимации должны уважать
prefers-reduced-motion, а модалки — блокировать фоновую прокрутку и закрываться Escape/кнопкой с доступной подписью. - Все сообщения об ошибках должны быть понятными; сохранение формы следует выполнять через заранее захваченный form reference до async/await.
12. Локальный запуск и production
node --version # Node.js 20+ cp .env.example .env # заполнить SESSION_SECRET, OTP_PEPPER, DATA_API_TOKEN, POSTGRES_PASSWORD, ADMIN_EMAIL, ADMIN_LOGIN и ADMIN_PASSWORD docker compose up --build # локально: http://localhost:3000/
Compose поднимает PostgreSQL, внутренний Data API и Platform API как отдельные сервисы. Platform API не получает DATABASE_URL и пароль PostgreSQL, а Data API не публикуется на host port. Игровые файлы и аватары по-прежнему сохраняются в постоянный storage/ volume; адаптер S3/GCS пока не подключён. Runtime manager выделен в отдельный внутренний сервис, который единственный подключён к Docker socket; Platform API вызывает его по внутреннему API с секретным токеном. Для production обязательны HTTPS, секреты через secret manager, reverse proxy/CDN/WAF, резервные копии с проверкой восстановления, мониторинг, политика конфиденциальности и условия использования. TRUST_PROXY=1 включается только за доверенным proxy. Серверные игры требуют доступного Docker Engine и runtime-образа, но в текущем Compose runtime manager ещё не выделен в отдельный сервис.
При автоматическом запуске опубликованных серверных игр приложение делает попытку поднять контейнер при старте. Если Docker недоступен или образ отсутствует, сама запись игры может быть published, но состояние пинга будет starting/offline и сообщение попадёт в server logs; публикация не равна подтверждённой готовности runtime.
13. План проверок и критерии приёмки
- Static checks:
npm run check, валидный JSON/package manifest, проверки client JS. - API smoke:
/api/bootstrap,/api/games,/robots.txt,/sitemap.xml, /api/admin/metrics для admin и отказ доступа для не-admin. - Archive pipeline: upload valid browser ZIP + valid server ZIP; тест отказа для traversal, absolute paths, symlinks, oversized archive, missing translations and invalid capsule size.
- Publishing: draft files закрыты от гостя, доступны администратору; публикация добавляет запись в каталог; unpublish/delete выключают runtime.
- SDK: getUser guest/auth, cloud save/load, review/rating/favorite/share, game event and activity timer.
- Server runtime: container health, port mapping, readiness retries, relative JS/CSS/image URLs, ping measurement, restart behavior, stop hooks.
- UX regressions: RU/EN persistence, docs/SDK RU/EN language switching, profile cancel/save/avatar thumbnail, comment avatar rendering, modal scroll-lock, reduced motion, mobile viewports.
- Operations: backups/restore, logging, disk quotas, host hardening, WAF behavior, SMTP delivery checks with real credentials.
14. Архитектурные решения (ADR summary)
ADR-001 · Platform API + internal Data API + PostgreSQL
Platform API владеет бизнес-правилами и HTTP-контрактом. Отдельный Data API — единственный компонент с драйвером PostgreSQL и принимает запросы только по реестру статических SQL-операторов с проверкой параметров; сырой SQL по сети не передаётся. Это уменьшает связанность и позволяет менять слой хранения без переделки публичного API. Express sessions также хранятся в PostgreSQL. Data API остаётся дополнительной точкой отказа, поэтому нужны health checks, тайм-ауты, backups и проверка транзакций.
ADR-002 · Vanilla JS вместо SPA-фреймворка
Каталог и админские страницы небольшие и преимущественно data-driven; нативный HTML/CSS/JS сокращает сборочную цепочку и упрощает отладку. При росте UI сложности допустимо выделить component system, не меняя REST-контракты.
ADR-003 · iframe sandbox для клиентских игр
Игра считается недоверенным code asset и не должна иметь same-origin доступ к сессии/DOM платформы. SDK bridge явный, узкий и валидирует список методов.
ADR-004 · Отдельный Docker container per server game
Нужен для server-authoritative multiplayer и пер-игровой изоляции. MVP использует локальный Docker manager и runtime probing; production следует дополнить лимитами числа одновременно работающих контейнеров, квотами CPU/disk, мониторингом, безопасной очисткой и возможным оркестратором.
ADR-005 · Server-computed score
Клиент не отправляет готовое число очков. Backend рассчитывает points из persisted sessions и допустимых действий, что устраняет простейшую накрутку подменой клиентского значения, но не заменяет антибот-модерацию.
ADR-006 · Localized descriptions, English title/tags
Отображаемое имя остаётся стабильным и индексируемым, описание зависит от языка, tags унифицированы на английском для каталожной фильтрации.
15. Приоритетный roadmap
- P0 — production validation: интеграционные тесты с чистой установкой зависимостей, миграции БД для существующих инсталляций, тесты на реальном Docker-хосте и проверки SMTP.
- P1 — operation: журналы контейнеров, рестарт/backoff, контейнерные квоты, health check, backups/restore drills, антивирус сканирования архивов, CSP и security audit.
- P1 — trust & safety: отчёты на отзывы/игры, moderation queue, anti-abuse thresholds, политика хранения и удаления аккаунта/данных.
- P1 — data reliability: проверить PostgreSQL/Data API на Docker Compose, добавить versioned schema migrations, backup/restore drills, тайм-ауты и контрактные тесты с реальной PostgreSQL.
- P2 — scale: вынести игровые ZIP/аватары/медиа в S3/GCS, выделить Docker runtime в отдельный ограниченный runtime-manager, добавить очередь фоновой аналитики и централизованный telemetry pipeline.
- P2 — product: SDK versioning, migration checks, preview diagnostics, automated compatibility checks и публикационный pipeline с release/rollback.