Stage 15: dual Telegram bots & language-gated variants #16

Merged
developer merged 2 commits from feature/stage-15-language-service-split into master 2026-06-05 07:40:53 +00:00
Showing only changes of commit 23b5c3b5cc - Show all commits
+19 -19
View File
@@ -48,9 +48,9 @@ independent (see ARCHITECTURE §9.1).
| 12 | Observability & performance (telemetry, metrics, guest GC) | **done** |
| 13 | Alphabet on the wire (UI alphabet-agnostic) | **done** |
| 14 | Solver & dictionary split (publish solver + scrabble-dictionary repo/artifact) | **done** |
| 15 | Deploy infra & test contour (Dockerfiles, gateway static UI, compose, observability) | todo |
| 16 | Prod contour deploy (SSH export/import, manual after merge) | todo |
| 17 | Dual Telegram bots & language-gated variants | todo |
| 15 | Dual Telegram bots & language-gated variants | todo |
| 16 | Deploy infra & test contour (Dockerfiles, gateway static UI, compose, observability) | todo |
| 17 | Prod contour deploy (SSH export/import, manual after merge) | todo |
Scaffolding is incremental: `go.work` lists only existing modules; each stage
adds the modules it needs.
@@ -264,7 +264,21 @@ both — discharging **TODO-1** and **TODO-2**.
`BACKEND_DICT_DIR/<version>/`, `engine.OpenWithVersions`, per-game `dict_version` pin; a version is
safe to retire once no active game pins it).
### Stage 15 — Deploy infra & test contour
### Stage 15 — Dual Telegram bots & language-gated variants *(feature; own interview)*
Scope (owner's idea, to design in detail at its own start): run **two bots in the one connector
container** — one for the English audience, one for Russian — each with its own token + game-channel id
+ service-language tag (the same Telegram user id spans both). `initData` validation tries each bot's
token in turn (none succeeds ⇒ invalid). The connector returns the **service language `en`/`ru`**;
`Notify`/`SendToUser` take a language key so the right bot delivers. The UI **gates the game-type
(variant) choice** by service language (en → English; ru → Russian + Эрудит).
Open details (own interview): which bot sends a notification for an **existing** game (game language vs
the player's service language) given one user id spans both bots; behaviour for **non-Telegram**
players (web/email/guest — ungated, or by interface language); the proto/wire changes
(`ValidateInitData` service-language field, a bot/language selector on the push RPCs); per-bot config +
tests. Engineering feedback already captured at the Stage 14 interview: the two-bots-in-one-container +
sequential validation + language-keyed routing model is sound.
### Stage 16 — Deploy infra & test contour
Scope: the deploy machinery + the **test contour** (the bulk of the original Stage 14). Backend +
gateway **Dockerfiles** (multi-stage distroless, mirroring the Stage 9 connector image); the gateway
gains **static UI serving****embedded** via `go:embed` (a node build stage in the gateway image),
@@ -282,7 +296,7 @@ h2c wrap — `/` + `/telegram/` mounts; a committed `dist` placeholder so `go bu
build); Postgres healthcheck/volume; whether the connector-scoped compose is retired for the root one;
collector/Tempo/Prometheus retention.
### Stage 16 — Prod contour deploy
### Stage 17 — Prod contour deploy
Scope: the **production contour** on a remote host over SSH. Deploy by **container export/import**
(`docker save``scp`/ssh → `docker load``docker compose up` on the remote), the SSH key + host IP
in Gitea secrets; **strictly manual** (`workflow_dispatch`) after a feature branch is merged to
@@ -292,20 +306,6 @@ convention.
Open details (re-interview): export/import vs a registry trade-off; prod domain/TLS at the remote
caddy; prod VPN; rollback.
### Stage 17 — Dual Telegram bots & language-gated variants *(feature; own interview)*
Scope (owner's idea, to design in detail at its own start): run **two bots in the one connector
container** — one for the English audience, one for Russian — each with its own token + game-channel id
+ service-language tag (the same Telegram user id spans both). `initData` validation tries each bot's
token in turn (none succeeds ⇒ invalid). The connector returns the **service language `en`/`ru`**;
`Notify`/`SendToUser` take a language key so the right bot delivers. The UI **gates the game-type
(variant) choice** by service language (en → English; ru → Russian + Эрудит).
Open details (own interview): which bot sends a notification for an **existing** game (game language vs
the player's service language) given one user id spans both bots; behaviour for **non-Telegram**
players (web/email/guest — ungated, or by interface language); the proto/wire changes
(`ValidateInitData` service-language field, a bot/language selector on the push RPCs); per-bot config +
tests. Engineering feedback already captured at the Stage 14 interview: the two-bots-in-one-container +
sequential validation + language-keyed routing model is sound.
## Refinements logged during implementation
- **Stage 0**: solver `replace` deferred to Stage 2 (nothing imports it yet;