docs(telegram): invert chat-gate strategy in docs; tune logs; i18n text
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 18s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m15s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 18s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m15s
- Bake the final default-allow + mute-the-ineligible strategy into docs/ARCHITECTURE.md, docs/FUNCTIONAL.md (+_ru), platform/telegram/README.md, the deploy compose comment and the PRERELEASE tracker. The live test proved a per-user grant cannot exceed a deny-by-default group (Telegram intersects the chat default with the per-user permission), so the chat allows sending by default and the bot restricts the ineligible instead of granting the eligible. - Lower the per-event chat_member trace and eligibility evaluation to Debug; keep the actual mute/unmute actions, the startup self-check and warnings at Info, so prod logs only what the bot did. - Update game.searchingForOpponent (Searching -> Waiting for opponent / Поиск -> Ждём соперника) and the quickmatch e2e assertions to match.
This commit is contained in:
+11
-7
@@ -997,13 +997,17 @@ sweeper for the gate — it recomputes against `now`). No operator identity is r
|
||||
Basic-Auth).
|
||||
|
||||
**Moderated discussion chat.** A channel's linked discussion group is gated by the Telegram bot
|
||||
(`TELEGRAM_CHAT_ID`): the group defaults to no-send, and a user may write only while they are
|
||||
**registered and neither admin-suspended nor holding the chat-only `chat_muted` role**
|
||||
(`eligible = registered AND NOT suspended AND NOT chat_muted` — the game suspension dominates). A
|
||||
single backend resolver behind `POST /api/v1/internal/chat-access` answers both directions: the
|
||||
bot's join-time `ResolveChatEligibility` (over the mTLS bot-link) grants write access to an
|
||||
eligible joiner, and a `chat_access_changed` event — emitted on a block/unblock, a `chat_muted`
|
||||
grant/revoke, or a temporary block lapsing (a dedicated `account.SuspensionSweeper`, since no
|
||||
(`TELEGRAM_CHAT_ID`). The group **allows sending by default** and the bot only **restricts**: Telegram
|
||||
intersects the chat default with each user's permission, so a per-user grant can never exceed a
|
||||
deny-by-default group — the gate must mute the ineligible, not grant the eligible. A user may write
|
||||
while they are **registered and neither admin-suspended nor holding the chat-only `chat_muted` role**
|
||||
(`eligible = registered AND NOT suspended AND NOT chat_muted` — the game suspension dominates); the bot
|
||||
**mutes** an ineligible member and **un-mutes** an eligible one it had muted, leaving an already-allowed
|
||||
eligible member untouched (it acts only when the current state differs, so it is idempotent and never
|
||||
loops on its own change). A single backend resolver behind `POST /api/v1/internal/chat-access` answers
|
||||
both directions: the bot's `ResolveChatEligibility` on a `chat_member` event (over the mTLS bot-link),
|
||||
and a `chat_access_changed` event — emitted on a block/unblock, a `chat_muted` grant/revoke, a first
|
||||
Telegram registration, or a temporary block lapsing (a dedicated `account.SuspensionSweeper`, since no
|
||||
request fires then) — drives a `ChatGate` command the gateway pushes to the bot. The bot applies it
|
||||
only to a member currently in the chat (a per-user `getChatMember` probe, since bots cannot list
|
||||
members); the signal is idempotent and is never an in-app or out-of-app message. `chat_muted` is an
|
||||
|
||||
+7
-7
@@ -323,13 +323,13 @@ plus the reason when one was given, and the app stops all background traffic wit
|
||||
temporary block lifts itself when it expires; the operator can also **unblock** from the user card
|
||||
at any time (games already lost stay lost).
|
||||
|
||||
Where the bot manages a channel's **linked discussion chat**, only a **registered** player who is
|
||||
**not blocked** may write there: the bot grants the right to write when such a player joins, while an
|
||||
unregistered or blocked one stays muted (the promo bot points newcomers at the game so they register).
|
||||
An operator can also **mute a player in the chat only** — a `chat_muted` role on the user card —
|
||||
without a full account block; an account block mutes them in the chat regardless. Muting/unmuting and
|
||||
blocking/unblocking take effect for a player already in the chat; one who is not in it is unaffected
|
||||
until they next join.
|
||||
Where the bot manages a channel's **linked discussion chat**, everyone may write by default and the
|
||||
bot **mutes** a player who is **not registered** or is **blocked**, un-muting them once they register
|
||||
or are unblocked. So an unregistered newcomer who comments is muted (the promo bot points them at the
|
||||
game to register, after which the bot restores their voice), and a registered, unblocked player simply
|
||||
writes. An operator can also **mute a player in the chat only** — a `chat_muted` role on the user card —
|
||||
without a full account block; an account block mutes them in the chat regardless. Muting and unmuting
|
||||
take effect for a player already in the chat; one who is not in it is unaffected until they next join.
|
||||
|
||||
From the user card the operator can also **top up a player's hint wallet**: an additive grant
|
||||
(1–100 hints per action) that raises the balance shown on the card. Grants are **raise-only** —
|
||||
|
||||
@@ -332,13 +332,14 @@ high-rate флага. С карточки пользователя операт
|
||||
истечении срока; оператор также может **разблокировать** с карточки пользователя в любой момент
|
||||
(уже проигранные партии не возвращаются).
|
||||
|
||||
Там, где бот ведёт **привязанный к каналу чат-обсуждение**, писать в нём может только
|
||||
**зарегистрированный** игрок, который **не заблокирован**: при входе такого игрока бот выдаёт право
|
||||
писать, а незарегистрированному или заблокированному — оставляет немым (промо-бот направляет
|
||||
новичков в игру, чтобы они зарегистрировались). Оператор также может **замьютить игрока только в
|
||||
чате** — роль `chat_muted` на карточке пользователя — без полной блокировки аккаунта; блокировка
|
||||
аккаунта всё равно мьютит его в чате. Мьют/размьют и блокировка/разблокировка срабатывают для
|
||||
игрока, уже находящегося в чате; того, кого в чате нет, это не затрагивает до его следующего входа.
|
||||
Там, где бот ведёт **привязанный к каналу чат-обсуждение**, по умолчанию писать может каждый, а бот
|
||||
**глушит** игрока, который **не зарегистрирован** или **заблокирован**, и снимает мьют, как только тот
|
||||
зарегистрируется или будет разблокирован. То есть незарегистрированного новичка, написавшего в чат,
|
||||
бот глушит (промо-бот направляет его в игру зарегистрироваться, после чего бот возвращает голос), а
|
||||
зарегистрированный незаблокированный игрок просто пишет. Оператор также может **замьютить игрока только
|
||||
в чате** — роль `chat_muted` на карточке пользователя — без полной блокировки аккаунта; блокировка
|
||||
аккаунта всё равно мьютит его в чате. Мьют и размьют срабатывают для игрока, уже находящегося в чате;
|
||||
того, кого в чате нет, это не затрагивает до его следующего входа.
|
||||
|
||||
С карточки пользователя оператор также может **пополнить кошелёк подсказок** игрока: аддитивное
|
||||
начисление (1–100 подсказок за раз), которое **только увеличивает** баланс на карточке. Начисления
|
||||
|
||||
Reference in New Issue
Block a user