МожливостіСутності
Документація
    Ring Platform

    Децентралізоване самобудівне майбутнє

    Увійти
    Сутності
    Можливості
    Магазин
    Документація
    Концепції
    RING ЕкономікаSonoratek LLCГлобальний впливAI зустрічає Web3
    Розпочати
    Швидкий стартКалькуляторДорожня карта
    Конфіденційність|Контакти
    v1.104.17|Sonoratek LLC

    Documentation

    Концепції, цінність і типові сценарії

    Ласкаво просимо до Ring
    Швидкий довідник
    Початок роботи
    Передумови
    Встановлення
    Валідація першого успіху
    Наступні кроки
    Функції
    Магазин
    Склад і залишки
    Керування вендорами
    Комісії та розрахунки
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Інтеграція платежів
    Публічні пули та DAO-банки
    Інтеграція WayForPay
    Web3 Гаманець
    WalletConductor
    Партнерська та реферальна підтримка
    Реферальні коди (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Система Стейкінга Токенів
    Лабораторія проєкту власника (Owner Project Lab)
    Сутності
    Можливості
    Повідомлення
    Завдання Ring
    WebRTC-дзвінки та STUNner TURN
    Ігри з друзями
    Модуль Новин - Цифровий Газетний Досвід
    Блоги учасників
    Сторінки публічного профілю
    Віджети профілю облікового запису
    Ring File Cabinet
    Система Резервування Імен Користувачів
    Науковий редактор
    Notifications
    Push-сповіщення через FCM (Ring)
    Email AI-CRM
    Ring Mailer і RingdomX Mail
    Протокол Tunnel
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Безпека та відповідність
    Консоль адміністратора
    Адмінська Wiki
    Керування через Telegram
    Система локалей
    Мобільний Досвід
    Паттерни Оптимізації Продуктивності
    Приклади
    Швидкий старт
    Базове налаштування
    Білий лейбл
    Користувацьке брендування
    Інтеграція Web3
    Реальні приклади
    Розширені функції
    Кастомізація
    Швидкий старт — ваш перший клон Ring
    Повний посібник налаштування
    Вертикальні пресети (SSOT)
    Ringization playbook
    Брендування
    Теми
    Функції
    Локалізація
    Налаштування токеноміки
    Інтеграція платіжних шлюзів
    Еталонні деплої Ring
    Конфігурація
    Публічні змінні середовища
    Секрети Order Lab
    Project ID WalletConnect (Reown Cloud)
    Підтримувані сервіси
    Вікі NODUS (знання проєкту)
    Плейбук конфігурації
    Web3
    Token launch jurisdictions
    Гаманець
    Поради з безпеки гаманця
    Інтеграції
    Ethereum гаманці (Wagmi v3)
    RingFileBase (API об’єктного сховища)
    Ring CDN (edge RingFileBase)
    Розгортання
    Self-hosted розгортання
    Vercel
    Docker
    Конфігурація Середовища
    Моніторинг та Аналітика
    Оптимізація продуктивності
    Резервне копіювання і відновлення
    Архітектура
    Data Model
    Security
    Real Time
    Синхронізація discovery після мутацій
    Архітектура PaymentConductor
    Архітектура WalletConductor
    Бекенд Сервіси
    Інтеграція Firebase
    Розробка
    Ring MCP Server

    Швидкий вхід (CTO · аудитори · агенти)

    Вітаємо — місія та аудиторії
    Швидкий довідник
    Початок роботи
    Архітектура та Auth.js
    Режими бекенду та БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безпека та відповідність
    ringdom.org — база LegioX
    Код — ліцензія MIT (GitHub)

    Documentation

    Концепції, цінність і типові сценарії

    Ласкаво просимо до Ring
    Швидкий довідник
    Початок роботи
    Передумови
    Встановлення
    Валідація першого успіху
    Наступні кроки
    Функції
    Магазин
    Склад і залишки
    Керування вендорами
    Комісії та розрахунки
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Інтеграція платежів
    Публічні пули та DAO-банки
    Інтеграція WayForPay
    Web3 Гаманець
    WalletConductor
    Партнерська та реферальна підтримка
    Реферальні коди (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Система Стейкінга Токенів
    Лабораторія проєкту власника (Owner Project Lab)
    Сутності
    Можливості
    Повідомлення
    Завдання Ring
    WebRTC-дзвінки та STUNner TURN
    Ігри з друзями
    Модуль Новин - Цифровий Газетний Досвід
    Блоги учасників
    Сторінки публічного профілю
    Віджети профілю облікового запису
    Ring File Cabinet
    Система Резервування Імен Користувачів
    Науковий редактор
    Notifications
    Push-сповіщення через FCM (Ring)
    Email AI-CRM
    Ring Mailer і RingdomX Mail
    Протокол Tunnel
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Безпека та відповідність
    Консоль адміністратора
    Адмінська Wiki
    Керування через Telegram
    Система локалей
    Мобільний Досвід
    Паттерни Оптимізації Продуктивності
    Приклади
    Швидкий старт
    Базове налаштування
    Білий лейбл
    Користувацьке брендування
    Інтеграція Web3
    Реальні приклади
    Розширені функції
    Кастомізація
    Швидкий старт — ваш перший клон Ring
    Повний посібник налаштування
    Вертикальні пресети (SSOT)
    Ringization playbook
    Брендування
    Теми
    Функції
    Локалізація
    Налаштування токеноміки
    Інтеграція платіжних шлюзів
    Еталонні деплої Ring
    Конфігурація
    Публічні змінні середовища
    Секрети Order Lab
    Project ID WalletConnect (Reown Cloud)
    Підтримувані сервіси
    Вікі NODUS (знання проєкту)
    Плейбук конфігурації
    Web3
    Token launch jurisdictions
    Гаманець
    Поради з безпеки гаманця
    Інтеграції
    Ethereum гаманці (Wagmi v3)
    RingFileBase (API об’єктного сховища)
    Ring CDN (edge RingFileBase)
    Розгортання
    Self-hosted розгортання
    Vercel
    Docker
    Конфігурація Середовища
    Моніторинг та Аналітика
    Оптимізація продуктивності
    Резервне копіювання і відновлення
    Архітектура
    Data Model
    Security
    Real Time
    Синхронізація discovery після мутацій
    Архітектура PaymentConductor
    Архітектура WalletConductor
    Бекенд Сервіси
    Інтеграція Firebase
    Розробка
    Ring MCP Server

    Швидкий вхід (CTO · аудитори · агенти)

    Вітаємо — місія та аудиторії
    Швидкий довідник
    Початок роботи
    Архітектура та Auth.js
    Режими бекенду та БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безпека та відповідність
    ringdom.org — база LegioX
    Код — ліцензія MIT (GitHub)

    Documentation

    Концепції, цінність і типові сценарії

    Ласкаво просимо до Ring
    Швидкий довідник
    Початок роботи
    Передумови
    Встановлення
    Валідація першого успіху
    Наступні кроки
    Функції
    Магазин
    Склад і залишки
    Керування вендорами
    Комісії та розрахунки
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Інтеграція платежів
    Публічні пули та DAO-банки
    Інтеграція WayForPay
    Web3 Гаманець
    WalletConductor
    Партнерська та реферальна підтримка
    Реферальні коди (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Система Стейкінга Токенів
    Лабораторія проєкту власника (Owner Project Lab)
    Сутності
    Можливості
    Повідомлення
    Завдання Ring
    WebRTC-дзвінки та STUNner TURN
    Ігри з друзями
    Модуль Новин - Цифровий Газетний Досвід
    Блоги учасників
    Сторінки публічного профілю
    Віджети профілю облікового запису
    Ring File Cabinet
    Система Резервування Імен Користувачів
    Науковий редактор
    Notifications
    Push-сповіщення через FCM (Ring)
    Email AI-CRM
    Ring Mailer і RingdomX Mail
    Протокол Tunnel
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Безпека та відповідність
    Консоль адміністратора
    Адмінська Wiki
    Керування через Telegram
    Система локалей
    Мобільний Досвід
    Паттерни Оптимізації Продуктивності
    Приклади
    Швидкий старт
    Базове налаштування
    Білий лейбл
    Користувацьке брендування
    Інтеграція Web3
    Реальні приклади
    Розширені функції
    Кастомізація
    Швидкий старт — ваш перший клон Ring
    Повний посібник налаштування
    Вертикальні пресети (SSOT)
    Ringization playbook
    Брендування
    Теми
    Функції
    Локалізація
    Налаштування токеноміки
    Інтеграція платіжних шлюзів
    Еталонні деплої Ring
    Конфігурація
    Публічні змінні середовища
    Секрети Order Lab
    Project ID WalletConnect (Reown Cloud)
    Підтримувані сервіси
    Вікі NODUS (знання проєкту)
    Плейбук конфігурації
    Web3
    Token launch jurisdictions
    Гаманець
    Поради з безпеки гаманця
    Інтеграції
    Ethereum гаманці (Wagmi v3)
    RingFileBase (API об’єктного сховища)
    Ring CDN (edge RingFileBase)
    Розгортання
    Self-hosted розгортання
    Vercel
    Docker
    Конфігурація Середовища
    Моніторинг та Аналітика
    Оптимізація продуктивності
    Резервне копіювання і відновлення
    Архітектура
    Data Model
    Security
    Real Time
    Синхронізація discovery після мутацій
    Архітектура PaymentConductor
    Архітектура WalletConductor
    Бекенд Сервіси
    Інтеграція Firebase
    Розробка
    Ring MCP Server

    Швидкий вхід (CTO · аудитори · агенти)

    Вітаємо — місія та аудиторії
    Швидкий довідник
    Початок роботи
    Архітектура та Auth.js
    Режими бекенду та БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безпека та відповідність
    ringdom.org — база LegioX
    Код — ліцензія MIT (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ігри з друзями

    Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб фільтрувати цю сторінку. Видимість у бічній панелі налаштовується в lib/docs/audience-curated-docs.ts.

    Ring постачає мініігри для друзів, які повторно використовують fan-out Tunnel, набір інтерактивних повідомлень і IA публічного профілю — без GameConductor, паралельного стека повідомлень чи ставок.

    ПоверхняШлях
    Маркетплейс/games
    Мініапка/games/[slug]?session=
    Публічна доступність/{username}/games
    Керування власника/profile/games (Member)
    Віджет чатутип повідомлення / metadata.kind = game_request
    Вхідний банерMessagesShell і layout /games

    Доступні назви: хрестики-нулики · шахи · шашки. Тексти каталогу локалізуються через locales/*/modules/games.json (modules.games); англійські рядки в catalog.ts залишаються резервним варіантом для FCM/історії.

    Чому це важливо для вашого клону

    Учасники швидше зближуються, коли можуть грати, не залишаючи ваш Ring. Виклики надходять як віджети чату та як глобальний IncomingGameBanner у Messages і /games — тож запрошення не губляться за межами гілки месенджера.

    • Безплатна перевага Member — без ставок Stars / кредитів / PaymentConductor
    • Лише прямі розмови (той самий gate, що й для дзвінків 1:1)
    • М’ютекс дзвінка ↔ гри (між вкладками через BroadcastChannel): не можна прийняти гру під час активного дзвінка і навпаки
    • Публічна дія Грати зі мною пропонує лише slug-и, які гравець увімкнув на /{username}/games
    • Неприйняті запрошення спливають через 15 хвилин; активні ігри бездіяльні та очищуються через 2 години

    Чекліст оператора

    1. Підтвердьте членство, щоб власники могли відкрити /profile/games і опублікувати доступність (шахи / шашки / хрестики-нулики).
    2. Перевірте /games у кожній локалі — назви каталогу мають локалізуватися (EN/UK/RU/ES/DE).
    3. У прямому чаті створіть ігровий виклик → співрозмовник бачить банер і віджет.
    4. Прийміть → зробіть ходи → здайтеся; обидві сторони оновлюються без перезавантаження.
    5. Переконайтеся, що телефонний/відеодзвінок блокує прийняття гри, поки накладка дзвінка активна (також спробуйте другу вкладку браузера).
    6. Необов’язково: залиште неприйняте запрошення приблизно на 15 хвилин (або запустіть cron завершення сесій) → банер і мініапка очищуються.

    Повідомлення

    Архітектура

    Ключові модулі

    ШляхРоль
    features/peer-games/service.tsСесії + доступність + SSOT createInvite
    features/peer-games/session-expiry.tsПовернення сиріт + завершення неприйнятих/неактивних сесій
    features/peer-games/plugins/*-logic.tsБезпечні для сервера validate/apply (ttt, chess, checkers)
    features/peer-games/catalog.tsРеєстр slug-ів (резервний EN)
    locales/*/modules/games.jsoni18n каталогу + маркетплейсу (modGames)
    features/peer-games/lib/peer-game-mutex.tsЗайнятість дзвінка/гри + BroadcastChannel / Web Locks
    features/peer-games/lib/catalog-i18n.tsХелпери локалізованих назв/описів

    Пов’язана документація

    Related documentation

    Real-Time Messaging

    Залежить від: game_request живе в наборі інтерактивних повідомлень і прямих розмовах.

    WebRTC Calls & STUNner TURN

    Той самий процес: спільний м’ютекс дзвінка/гри; маршрут ICE повторно використовується для підказок ходів DataChannel.

    Tunnel Protocol

    Залежить від: ACL conversation:*, game:{sessionId} і fan-out games:incoming.

    SubscriptionConductor

    Передумова: привілеї Member керують /profile/games і створенням викликів.

    Ігри з друзями

    Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб фільтрувати цю сторінку. Видимість у бічній панелі налаштовується в lib/docs/audience-curated-docs.ts.

    Ring постачає мініігри для друзів, які повторно використовують fan-out Tunnel, набір інтерактивних повідомлень і IA публічного профілю — без GameConductor, паралельного стека повідомлень чи ставок.

    ПоверхняШлях
    Маркетплейс/games
    Мініапка/games/[slug]?session=
    Публічна доступність/{username}/games
    Керування власника/profile/games (Member)
    Віджет чатутип повідомлення / metadata.kind = game_request
    Вхідний банерMessagesShell і layout /games

    Доступні назви: хрестики-нулики · шахи · шашки. Тексти каталогу локалізуються через locales/*/modules/games.json (modules.games); англійські рядки в catalog.ts залишаються резервним варіантом для FCM/історії.

    Чому це важливо для вашого клону

    Учасники швидше зближуються, коли можуть грати, не залишаючи ваш Ring. Виклики надходять як віджети чату та як глобальний IncomingGameBanner у Messages і /games — тож запрошення не губляться за межами гілки месенджера.

    • Безплатна перевага Member — без ставок Stars / кредитів / PaymentConductor
    • Лише прямі розмови (той самий gate, що й для дзвінків 1:1)
    • М’ютекс дзвінка ↔ гри (між вкладками через BroadcastChannel): не можна прийняти гру під час активного дзвінка і навпаки
    • Публічна дія Грати зі мною пропонує лише slug-и, які гравець увімкнув на /{username}/games
    • Неприйняті запрошення спливають через 15 хвилин; активні ігри бездіяльні та очищуються через 2 години

    Чекліст оператора

    1. Підтвердьте членство, щоб власники могли відкрити /profile/games і опублікувати доступність (шахи / шашки / хрестики-нулики).
    2. Перевірте /games у кожній локалі — назви каталогу мають локалізуватися (EN/UK/RU/ES/DE).
    3. У прямому чаті створіть ігровий виклик → співрозмовник бачить банер і віджет.
    4. Прийміть → зробіть ходи → здайтеся; обидві сторони оновлюються без перезавантаження.
    5. Переконайтеся, що телефонний/відеодзвінок блокує прийняття гри, поки накладка дзвінка активна (також спробуйте другу вкладку браузера).
    6. Необов’язково: залиште неприйняте запрошення приблизно на 15 хвилин (або запустіть cron завершення сесій) → банер і мініапка очищуються.

    Повідомлення

    Архітектура

    Ключові модулі

    ШляхРоль
    features/peer-games/service.tsСесії + доступність + SSOT createInvite
    features/peer-games/session-expiry.tsПовернення сиріт + завершення неприйнятих/неактивних сесій
    features/peer-games/plugins/*-logic.tsБезпечні для сервера validate/apply (ttt, chess, checkers)
    features/peer-games/catalog.tsРеєстр slug-ів (резервний EN)
    locales/*/modules/games.jsoni18n каталогу + маркетплейсу (modGames)
    features/peer-games/lib/peer-game-mutex.tsЗайнятість дзвінка/гри + BroadcastChannel / Web Locks
    features/peer-games/lib/catalog-i18n.tsХелпери локалізованих назв/описів

    Пов’язана документація

    Related documentation

    Real-Time Messaging

    Залежить від: game_request живе в наборі інтерактивних повідомлень і прямих розмовах.

    WebRTC Calls & STUNner TURN

    Той самий процес: спільний м’ютекс дзвінка/гри; маршрут ICE повторно використовується для підказок ходів DataChannel.

    Tunnel Protocol

    Залежить від: ACL conversation:*, game:{sessionId} і fan-out games:incoming.

    SubscriptionConductor

    Передумова: привілеї Member керують /profile/games і створенням викликів.

    Ігри з друзями

    Використовуйте вкладки Founder / Developer на бічній панелі документації, щоб фільтрувати цю сторінку. Видимість у бічній панелі налаштовується в lib/docs/audience-curated-docs.ts.

    Ring постачає мініігри для друзів, які повторно використовують fan-out Tunnel, набір інтерактивних повідомлень і IA публічного профілю — без GameConductor, паралельного стека повідомлень чи ставок.

    ПоверхняШлях
    Маркетплейс/games
    Мініапка/games/[slug]?session=
    Публічна доступність/{username}/games
    Керування власника/profile/games (Member)
    Віджет чатутип повідомлення / metadata.kind = game_request
    Вхідний банерMessagesShell і layout /games

    Доступні назви: хрестики-нулики · шахи · шашки. Тексти каталогу локалізуються через locales/*/modules/games.json (modules.games); англійські рядки в catalog.ts залишаються резервним варіантом для FCM/історії.

    Чому це важливо для вашого клону

    Учасники швидше зближуються, коли можуть грати, не залишаючи ваш Ring. Виклики надходять як віджети чату та як глобальний IncomingGameBanner у Messages і /games — тож запрошення не губляться за межами гілки месенджера.

    • Безплатна перевага Member — без ставок Stars / кредитів / PaymentConductor
    • Лише прямі розмови (той самий gate, що й для дзвінків 1:1)
    • М’ютекс дзвінка ↔ гри (між вкладками через BroadcastChannel): не можна прийняти гру під час активного дзвінка і навпаки
    • Публічна дія Грати зі мною пропонує лише slug-и, які гравець увімкнув на /{username}/games
    • Неприйняті запрошення спливають через 15 хвилин; активні ігри бездіяльні та очищуються через 2 години

    Чекліст оператора

    1. Підтвердьте членство, щоб власники могли відкрити /profile/games і опублікувати доступність (шахи / шашки / хрестики-нулики).
    2. Перевірте /games у кожній локалі — назви каталогу мають локалізуватися (EN/UK/RU/ES/DE).
    3. У прямому чаті створіть ігровий виклик → співрозмовник бачить банер і віджет.
    4. Прийміть → зробіть ходи → здайтеся; обидві сторони оновлюються без перезавантаження.
    5. Переконайтеся, що телефонний/відеодзвінок блокує прийняття гри, поки накладка дзвінка активна (також спробуйте другу вкладку браузера).
    6. Необов’язково: залиште неприйняте запрошення приблизно на 15 хвилин (або запустіть cron завершення сесій) → банер і мініапка очищуються.

    Повідомлення

    Архітектура

    Ключові модулі

    ШляхРоль
    features/peer-games/service.tsСесії + доступність + SSOT createInvite
    features/peer-games/session-expiry.tsПовернення сиріт + завершення неприйнятих/неактивних сесій
    features/peer-games/plugins/*-logic.tsБезпечні для сервера validate/apply (ttt, chess, checkers)
    features/peer-games/catalog.tsРеєстр slug-ів (резервний EN)
    locales/*/modules/games.jsoni18n каталогу + маркетплейсу (modGames)
    features/peer-games/lib/peer-game-mutex.tsЗайнятість дзвінка/гри + BroadcastChannel / Web Locks
    features/peer-games/lib/catalog-i18n.tsХелпери локалізованих назв/описів

    Пов’язана документація

    Related documentation

    Real-Time Messaging

    Залежить від: game_request живе в наборі інтерактивних повідомлень і прямих розмовах.

    WebRTC Calls & STUNner TURN

    Той самий процес: спільний м’ютекс дзвінка/гри; маршрут ICE повторно використовується для підказок ходів DataChannel.

    Tunnel Protocol

    Залежить від: ACL conversation:*, game:{sessionId} і fan-out games:incoming.

    SubscriptionConductor

    Передумова: привілеї Member керують /profile/games і створенням викликів.

    Розмови та інтерактивні віджети (game_request у спільному наборі).

    Дзвінки WebRTC

    Спільний м’ютекс дзвінка/гри; ICE-хелпер повторно використовується для оптимістичних підказок ходів DataChannel.

    Членство

    Gate Member для публікації доступності та створення викликів.

    Публічний профіль

    /{username}/games розташований поруч із Player і Gallery у публічному профілі.

    features/peer-games/hooks/use-peer-game-datachannel.tsОптимістичні підказки ходів (ring-peer-game-moves)
    app/_actions/peer-games.tsСерверні дії
    app/api/conversations/[id]/game-invite/route.tsТонкий HTTP-аналог → createInvite
    app/api/cron/peer-game-session-expiry/route.tsКонвеєр ProcessConductor
    app/api/tunnel/subscribe/route.tsACL учасників HTTP game:*
    lib/tunnel/native-ws/attach.tsACL учасників WS game:* (віддзеркалює HTTP)
    IncomingGameBannerОчищення життєвого циклу games:incoming + game:{id}

    Збереження даних

    Міграція data/migrations/043_peer_games.sql:

    • peer_game_sessions — індекси за conversation / challenger / peer / status / slug / messageId / updated_at
    • user_peer_games — enabledSlugs для кожного власника (унікальне поле ownerId)

    Канали Tunnel (перевірено)

    КаналПодії
    conversation:{id}game:invite, game:accept, game:decline, game:resign, game:move, game:expire
    game:{sessionId}game:accept, game:decline, game:resign, game:move, game:expire, game:dc-signal
    інбокс користувачаgames:incoming (invite, accepted, terminal)

    ACL підписки: для game:{sessionId} за замовчуванням доступ заборонено і через HTTP, і через native WS — лише учасники з БД (getSessionForParticipant). Спостереження відкладено.

    Очищення банера: game:expire / game:decline / game:accept на каналі сесії, а також games:incoming із terminal або accepted (охоплює гонку підписки після запрошення).

    Сповіщення та FCM

    NotificationType.GAME_REQUEST / GAME_UPDATED. Офлайн-push: після !deliveredLive зачекати приблизно 500 мс і повторно перевірити getTunnelHub().isUserConnected(peer) перед createNotification + PUSH dual-stack (FCM Admin і RFC web-push). На банері — лише м’який сигнал Web Audio; ніколи не викликайте ringtone / setPeerCallBusy. На пристроях, якими керує Chrome FCM, push_subscriptions порожній (RFC — no-op). Див. Push-сповіщення (FCM).

    isUserConnected хаба локальний для процесу. Хибний офлайн FCM у multi-pod — відома залишкова проблема; спільна presence ще в беклозі.

    М’ютекс, дедуплікація, дошки

    • М’ютекс: setPeerCallBusy / setPeerGameBusy з BroadcastChannel (+ опційно navigator.locks)
    • Дедуплікація запрошень: Redis SET NX PX усередині createInvite (спершу claim; у разі помилки — releaseNx) — Server Action + HTTP + Play-with-me спільно використовують SSOT
    • Шахи: FEN SSOT (key={fen}); невалідні ходи повертають false
    • Шашки: англійські шашки, обов’язкове взяття, один стрибок за хід (ланцюжок стрибків — у беклозі)

    Завершення сесій

    Конвеєр peer-game-session-expiry:

    ВипадокTTLРезультат
    Осиротіла неприйнята сесія (без messageId)~2mПовернення
    Неприйняте запрошення15mВідхилено + updateMessageLocked
    Активна бездіяльність2hЗдано/завершено + сповіщення Tunnel

    Планувальники: Vercel */5 (vercel.json) · k3s-or CronJobs infrastructure/k3s-or/ring-platform-org/cronjob-peer-game-session-expiry.yaml (+ сусідній cronjob-close-expired-polls.yaml, /bin/sh, щоб розгортати CRON_SECRET). Застосуйте в кластері під час переведення k8s prod.

    DataChannel (лише оптимістичний режим)

    RTCDataChannel із міткою ring-peer-game-moves (ordered) + fetchIceServers. Конверти peer — це підказки; validateMove / Tunnel game:move / БД залишаються SSOT. Відхилення → відкат до останнього авторитетного hydrate. Перезапуск ICE у нестабільних мережах — у беклозі; шлях Tunnel залишається резервним.

    Серверні дії

    createGameRequest · acceptGameRequest · declineGameRequest · resignPeerGameAction · submitPeerGameMoveAction · getPeerGameSessionAction · updateEnabledGamesAction · challengeUserToGameAction

    Smoke / soak

    Структурна перевірка: npx tsx scripts/smoke-peer-games-soak.cts. Модульні тести плагінів у __tests__/features/peer-games/plugins.test.ts. Чекліст live E2E для Member: AI-CONTEXT/concepts/peer-games-live-e2e-soak-2026-07-24.json (поширення empire Reggie заблоковане до погодження).

    Public Profile Pages

    Наступний крок: публічний /{username}/games поруч із Player і Gallery.

    Push Notifications with FCM (Ring-Powered)

    Також див.: createInvite PUSH GAME_REQUEST (FCM + RFC fan-out) після grace-періоду присутності Tunnel.

    Notifications

    Також див.: типи налаштувань GAME_REQUEST і GAME_UPDATED.

    text
    
    createGameRequest / POST …/game-invite / challengeUserToGameAction
      → PeerGameService.createInvite (SSOT)
      → Redis SET NX claim peer-game:invite:{from}:{to}:{slug} (Map fallback)
      → create session (peer_game_sessions) FIRST
      → send game_request message → link messageId
      → on failure: delete session + releaseNx
      → publishToChannel(conversation:…, game:invite)
      → publishToUserTunnel(peer, games:incoming)
      → if !deliveredLive: sleep ~500ms; FCM GAME_REQUEST only if still !isUserConnected
    accept / decline / resign / submitMove
      → participant ACL + plugin validateMove/applyMove
      → updateMessageLocked on linked widget metadata
      → game:* on game:{sessionId} AND conversation:{id}
      → decline/expire also publish terminal on games:incoming (banner clear)
    client mini-app
      → hydrate DB SSOT → useTunnelChannel(game:{id})
      → optional RTCDataChannel optimistic hints (fetchIceServers); server remains SSOT

    Розмови та інтерактивні віджети (game_request у спільному наборі).

    Дзвінки WebRTC

    Спільний м’ютекс дзвінка/гри; ICE-хелпер повторно використовується для оптимістичних підказок ходів DataChannel.

    Членство

    Gate Member для публікації доступності та створення викликів.

    Публічний профіль

    /{username}/games розташований поруч із Player і Gallery у публічному профілі.

    features/peer-games/hooks/use-peer-game-datachannel.tsОптимістичні підказки ходів (ring-peer-game-moves)
    app/_actions/peer-games.tsСерверні дії
    app/api/conversations/[id]/game-invite/route.tsТонкий HTTP-аналог → createInvite
    app/api/cron/peer-game-session-expiry/route.tsКонвеєр ProcessConductor
    app/api/tunnel/subscribe/route.tsACL учасників HTTP game:*
    lib/tunnel/native-ws/attach.tsACL учасників WS game:* (віддзеркалює HTTP)
    IncomingGameBannerОчищення життєвого циклу games:incoming + game:{id}

    Збереження даних

    Міграція data/migrations/043_peer_games.sql:

    • peer_game_sessions — індекси за conversation / challenger / peer / status / slug / messageId / updated_at
    • user_peer_games — enabledSlugs для кожного власника (унікальне поле ownerId)

    Канали Tunnel (перевірено)

    КаналПодії
    conversation:{id}game:invite, game:accept, game:decline, game:resign, game:move, game:expire
    game:{sessionId}game:accept, game:decline, game:resign, game:move, game:expire, game:dc-signal
    інбокс користувачаgames:incoming (invite, accepted, terminal)

    ACL підписки: для game:{sessionId} за замовчуванням доступ заборонено і через HTTP, і через native WS — лише учасники з БД (getSessionForParticipant). Спостереження відкладено.

    Очищення банера: game:expire / game:decline / game:accept на каналі сесії, а також games:incoming із terminal або accepted (охоплює гонку підписки після запрошення).

    Сповіщення та FCM

    NotificationType.GAME_REQUEST / GAME_UPDATED. Офлайн-push: після !deliveredLive зачекати приблизно 500 мс і повторно перевірити getTunnelHub().isUserConnected(peer) перед createNotification + PUSH dual-stack (FCM Admin і RFC web-push). На банері — лише м’який сигнал Web Audio; ніколи не викликайте ringtone / setPeerCallBusy. На пристроях, якими керує Chrome FCM, push_subscriptions порожній (RFC — no-op). Див. Push-сповіщення (FCM).

    isUserConnected хаба локальний для процесу. Хибний офлайн FCM у multi-pod — відома залишкова проблема; спільна presence ще в беклозі.

    М’ютекс, дедуплікація, дошки

    • М’ютекс: setPeerCallBusy / setPeerGameBusy з BroadcastChannel (+ опційно navigator.locks)
    • Дедуплікація запрошень: Redis SET NX PX усередині createInvite (спершу claim; у разі помилки — releaseNx) — Server Action + HTTP + Play-with-me спільно використовують SSOT
    • Шахи: FEN SSOT (key={fen}); невалідні ходи повертають false
    • Шашки: англійські шашки, обов’язкове взяття, один стрибок за хід (ланцюжок стрибків — у беклозі)

    Завершення сесій

    Конвеєр peer-game-session-expiry:

    ВипадокTTLРезультат
    Осиротіла неприйнята сесія (без messageId)~2mПовернення
    Неприйняте запрошення15mВідхилено + updateMessageLocked
    Активна бездіяльність2hЗдано/завершено + сповіщення Tunnel

    Планувальники: Vercel */5 (vercel.json) · k3s-or CronJobs infrastructure/k3s-or/ring-platform-org/cronjob-peer-game-session-expiry.yaml (+ сусідній cronjob-close-expired-polls.yaml, /bin/sh, щоб розгортати CRON_SECRET). Застосуйте в кластері під час переведення k8s prod.

    DataChannel (лише оптимістичний режим)

    RTCDataChannel із міткою ring-peer-game-moves (ordered) + fetchIceServers. Конверти peer — це підказки; validateMove / Tunnel game:move / БД залишаються SSOT. Відхилення → відкат до останнього авторитетного hydrate. Перезапуск ICE у нестабільних мережах — у беклозі; шлях Tunnel залишається резервним.

    Серверні дії

    createGameRequest · acceptGameRequest · declineGameRequest · resignPeerGameAction · submitPeerGameMoveAction · getPeerGameSessionAction · updateEnabledGamesAction · challengeUserToGameAction

    Smoke / soak

    Структурна перевірка: npx tsx scripts/smoke-peer-games-soak.cts. Модульні тести плагінів у __tests__/features/peer-games/plugins.test.ts. Чекліст live E2E для Member: AI-CONTEXT/concepts/peer-games-live-e2e-soak-2026-07-24.json (поширення empire Reggie заблоковане до погодження).

    Public Profile Pages

    Наступний крок: публічний /{username}/games поруч із Player і Gallery.

    Push Notifications with FCM (Ring-Powered)

    Також див.: createInvite PUSH GAME_REQUEST (FCM + RFC fan-out) після grace-періоду присутності Tunnel.

    Notifications

    Також див.: типи налаштувань GAME_REQUEST і GAME_UPDATED.

    text
    
    createGameRequest / POST …/game-invite / challengeUserToGameAction
      → PeerGameService.createInvite (SSOT)
      → Redis SET NX claim peer-game:invite:{from}:{to}:{slug} (Map fallback)
      → create session (peer_game_sessions) FIRST
      → send game_request message → link messageId
      → on failure: delete session + releaseNx
      → publishToChannel(conversation:…, game:invite)
      → publishToUserTunnel(peer, games:incoming)
      → if !deliveredLive: sleep ~500ms; FCM GAME_REQUEST only if still !isUserConnected
    accept / decline / resign / submitMove
      → participant ACL + plugin validateMove/applyMove
      → updateMessageLocked on linked widget metadata
      → game:* on game:{sessionId} AND conversation:{id}
      → decline/expire also publish terminal on games:incoming (banner clear)
    client mini-app
      → hydrate DB SSOT → useTunnelChannel(game:{id})
      → optional RTCDataChannel optimistic hints (fetchIceServers); server remains SSOT

    Розмови та інтерактивні віджети (game_request у спільному наборі).

    Дзвінки WebRTC

    Спільний м’ютекс дзвінка/гри; ICE-хелпер повторно використовується для оптимістичних підказок ходів DataChannel.

    Членство

    Gate Member для публікації доступності та створення викликів.

    Публічний профіль

    /{username}/games розташований поруч із Player і Gallery у публічному профілі.

    features/peer-games/hooks/use-peer-game-datachannel.tsОптимістичні підказки ходів (ring-peer-game-moves)
    app/_actions/peer-games.tsСерверні дії
    app/api/conversations/[id]/game-invite/route.tsТонкий HTTP-аналог → createInvite
    app/api/cron/peer-game-session-expiry/route.tsКонвеєр ProcessConductor
    app/api/tunnel/subscribe/route.tsACL учасників HTTP game:*
    lib/tunnel/native-ws/attach.tsACL учасників WS game:* (віддзеркалює HTTP)
    IncomingGameBannerОчищення життєвого циклу games:incoming + game:{id}

    Збереження даних

    Міграція data/migrations/043_peer_games.sql:

    • peer_game_sessions — індекси за conversation / challenger / peer / status / slug / messageId / updated_at
    • user_peer_games — enabledSlugs для кожного власника (унікальне поле ownerId)

    Канали Tunnel (перевірено)

    КаналПодії
    conversation:{id}game:invite, game:accept, game:decline, game:resign, game:move, game:expire
    game:{sessionId}game:accept, game:decline, game:resign, game:move, game:expire, game:dc-signal
    інбокс користувачаgames:incoming (invite, accepted, terminal)

    ACL підписки: для game:{sessionId} за замовчуванням доступ заборонено і через HTTP, і через native WS — лише учасники з БД (getSessionForParticipant). Спостереження відкладено.

    Очищення банера: game:expire / game:decline / game:accept на каналі сесії, а також games:incoming із terminal або accepted (охоплює гонку підписки після запрошення).

    Сповіщення та FCM

    NotificationType.GAME_REQUEST / GAME_UPDATED. Офлайн-push: після !deliveredLive зачекати приблизно 500 мс і повторно перевірити getTunnelHub().isUserConnected(peer) перед createNotification + PUSH dual-stack (FCM Admin і RFC web-push). На банері — лише м’який сигнал Web Audio; ніколи не викликайте ringtone / setPeerCallBusy. На пристроях, якими керує Chrome FCM, push_subscriptions порожній (RFC — no-op). Див. Push-сповіщення (FCM).

    isUserConnected хаба локальний для процесу. Хибний офлайн FCM у multi-pod — відома залишкова проблема; спільна presence ще в беклозі.

    М’ютекс, дедуплікація, дошки

    • М’ютекс: setPeerCallBusy / setPeerGameBusy з BroadcastChannel (+ опційно navigator.locks)
    • Дедуплікація запрошень: Redis SET NX PX усередині createInvite (спершу claim; у разі помилки — releaseNx) — Server Action + HTTP + Play-with-me спільно використовують SSOT
    • Шахи: FEN SSOT (key={fen}); невалідні ходи повертають false
    • Шашки: англійські шашки, обов’язкове взяття, один стрибок за хід (ланцюжок стрибків — у беклозі)

    Завершення сесій

    Конвеєр peer-game-session-expiry:

    ВипадокTTLРезультат
    Осиротіла неприйнята сесія (без messageId)~2mПовернення
    Неприйняте запрошення15mВідхилено + updateMessageLocked
    Активна бездіяльність2hЗдано/завершено + сповіщення Tunnel

    Планувальники: Vercel */5 (vercel.json) · k3s-or CronJobs infrastructure/k3s-or/ring-platform-org/cronjob-peer-game-session-expiry.yaml (+ сусідній cronjob-close-expired-polls.yaml, /bin/sh, щоб розгортати CRON_SECRET). Застосуйте в кластері під час переведення k8s prod.

    DataChannel (лише оптимістичний режим)

    RTCDataChannel із міткою ring-peer-game-moves (ordered) + fetchIceServers. Конверти peer — це підказки; validateMove / Tunnel game:move / БД залишаються SSOT. Відхилення → відкат до останнього авторитетного hydrate. Перезапуск ICE у нестабільних мережах — у беклозі; шлях Tunnel залишається резервним.

    Серверні дії

    createGameRequest · acceptGameRequest · declineGameRequest · resignPeerGameAction · submitPeerGameMoveAction · getPeerGameSessionAction · updateEnabledGamesAction · challengeUserToGameAction

    Smoke / soak

    Структурна перевірка: npx tsx scripts/smoke-peer-games-soak.cts. Модульні тести плагінів у __tests__/features/peer-games/plugins.test.ts. Чекліст live E2E для Member: AI-CONTEXT/concepts/peer-games-live-e2e-soak-2026-07-24.json (поширення empire Reggie заблоковане до погодження).

    Public Profile Pages

    Наступний крок: публічний /{username}/games поруч із Player і Gallery.

    Push Notifications with FCM (Ring-Powered)

    Також див.: createInvite PUSH GAME_REQUEST (FCM + RFC fan-out) після grace-періоду присутності Tunnel.

    Notifications

    Також див.: типи налаштувань GAME_REQUEST і GAME_UPDATED.

    text
    
    createGameRequest / POST …/game-invite / challengeUserToGameAction
      → PeerGameService.createInvite (SSOT)
      → Redis SET NX claim peer-game:invite:{from}:{to}:{slug} (Map fallback)
      → create session (peer_game_sessions) FIRST
      → send game_request message → link messageId
      → on failure: delete session + releaseNx
      → publishToChannel(conversation:…, game:invite)
      → publishToUserTunnel(peer, games:incoming)
      → if !deliveredLive: sleep ~500ms; FCM GAME_REQUEST only if still !isUserConnected
    accept / decline / resign / submitMove
      → participant ACL + plugin validateMove/applyMove
      → updateMessageLocked on linked widget metadata
      → game:* on game:{sessionId} AND conversation:{id}
      → decline/expire also publish terminal on games:incoming (banner clear)
    client mini-app
      → hydrate DB SSOT → useTunnelChannel(game:{id})
      → optional RTCDataChannel optimistic hints (fetchIceServers); server remains SSOT
    1. Документація
    2. /Функції
    3. /Ігри з друзями

    Оновлено 6 вер. 2026 р.5 хв прослуховування

    1. Документація
    2. /Функції
    3. /Ігри з друзями

    Оновлено 6 вер. 2026 р.5 хв прослуховування

    1. Документація
    2. /Функції
    3. /Ігри з друзями

    Оновлено 6 вер. 2026 р.5 хв прослуховування