R6(a): de-stage code, docs, READMEs; split stage6_test
Mechanical, behaviour-preserving removal of Stage N / TODO-N / phase (RN) references from comments, doc-comments, service READMEs, the current-state docs (ARCHITECTURE, FUNCTIONAL+_ru, TESTING, UI_DESIGN), config-file comments, and the .fbs/.proto schema comments. PLAN.md / PRERELEASE.md / CLAUDE.md keep the stage history. - Rename the only stage-named identifiers: registerStage8 -> registerSocialOps, registerStage11 -> registerLinkOps (gateway transcode). - Split stage6_test.go: TestEmailLoginFlow -> email_test.go, TestGuestAutoMatchLeavesNoStats (+ provisionGuest) -> account_test.go. - Regenerated proto bindings (push.pb.go, telegram_grpc.pb.go) from the de-staged .proto comments; FB Go/TS bindings unchanged (flatc strips schema comments). go build/vet/gofmt clean across modules; integration typecheck and pnpm check green.
This commit is contained in:
+19
-20
@@ -4,18 +4,17 @@ Per-domain user stories: what each user-visible operation does. This is the
|
||||
starting point for any change request that touches behaviour. The English
|
||||
version is authoritative; [`FUNCTIONAL_ru.md`](FUNCTIONAL_ru.md) is a mirror for
|
||||
the project owner — mirror every point edit in the same patch (translate only
|
||||
the changed paragraphs). Sections deepen as stages land; *(Stage N)* marks where
|
||||
the detail is authored.
|
||||
the changed paragraphs).
|
||||
|
||||
## Domains
|
||||
|
||||
### Client app *(Stage 7 / 8)*
|
||||
The web/app client (Svelte + Vite) realizes these stories. The **playable slice**
|
||||
(Stage 7) covers signing in (guest or email), the "my games" lobby, starting an
|
||||
### Client app
|
||||
The web/app client (Svelte + Vite) realizes these stories. It
|
||||
covers signing in (guest or email), the "my games" lobby, starting an
|
||||
auto-match, playing the board (place tiles by drag or tap, pass, exchange, resign),
|
||||
the top-1 hint, the unlimited word-check with complaint, per-game chat and nudge,
|
||||
real-time in-app updates, switching interface language (en/ru) and theme, and a
|
||||
read-only profile. **Stage 8** adds managing friends (including one-time friend
|
||||
read-only profile. It also handles managing friends (including one-time friend
|
||||
codes) and blocks, friend-game invitations, editing the profile and binding an
|
||||
email, the statistics screen, and the in-game history viewer with GCG export.
|
||||
Settings also pick the board's bonus-label style (beginner / classic / none). A hint **lays the suggested tiles on the board** for the player to confirm and
|
||||
@@ -26,7 +25,7 @@ theme, and links to the matching per-language Telegram channel; the game itself
|
||||
`/app/` (web) and `/telegram/` (the Telegram Mini App). The landing's theme is ephemeral
|
||||
(it follows the system scheme, not the saved preference); its language choice is saved.
|
||||
|
||||
### Identity & sessions *(Stage 1 / 6 / 9 / 15)*
|
||||
### Identity & sessions
|
||||
A player arrives from a platform (Telegram first), via email login, or as an
|
||||
ephemeral guest. The gateway validates the credential once and mints a thin
|
||||
session token; the backend resolves it to an internal `user_id`. A **Telegram Mini
|
||||
@@ -56,7 +55,7 @@ pause until it is back (a server-data screen still opens, with the spinner, and
|
||||
reconnect), and pending reads resume on their own — the interface stays usable instead of
|
||||
flashing a red banner each time.
|
||||
|
||||
### Accounts, linking & merge *(Stage 1 / 11)*
|
||||
### Accounts, linking & merge
|
||||
First platform contact auto-provisions a durable account. From the profile a player
|
||||
links an email (via a confirm code) or their Telegram (via the web sign-in); a guest
|
||||
who links their first identity becomes a durable account. The "already taken" status
|
||||
@@ -68,12 +67,12 @@ when a guest links an identity that already has a durable account, where the dur
|
||||
account is kept and the guest's games move into it. A merge is blocked only while the
|
||||
two accounts share a game still in progress.
|
||||
|
||||
### Lobby & matchmaking *(Stage 4 / 15)*
|
||||
### Lobby & matchmaking
|
||||
Bottom tab menu: **my games**, **profile**. The **my games** list groups games into three
|
||||
sections — *your turn*, *opponent's turn* and *finished* (empty sections are hidden) — and
|
||||
orders them so the games awaiting your move come first, the longest-waiting on top, while
|
||||
opponent-turn and finished games are most-recent first; it renders as a compact,
|
||||
line-separated list (Stage 17). You can **remove a finished game from your own list**:
|
||||
line-separated list. You can **remove a finished game from your own list**:
|
||||
swipe a finished row left (or, on desktop, tap its **⋮**) to reveal a **❌**, then tap it.
|
||||
The removal is per-account and permanent — the game disappears only from your list and stays
|
||||
in the other players' lists, and there is no undo. The game types offered on **New Game** are
|
||||
@@ -84,13 +83,13 @@ unrestricted). Variants are shown by their **display name** — both Scrabble va
|
||||
the same name titles the in-game screen. This gates only **starting** a new game — both auto-match and a friend
|
||||
invitation — so a player still sees and plays existing games of any language. Auto-match
|
||||
(always 2 players) joins a per-variant pool and is paired with the next waiting human;
|
||||
after 10 s with no human the robot substitutes (the robot arrives in Stage 5). Friend games (2–4) are
|
||||
after 10 s with no human the robot substitutes. Friend games (2–4) are
|
||||
formed by inviting players from the friend list (an invitation, like a friend code,
|
||||
is shareable as a Telegram deep link that opens it directly): the inviter chooses the
|
||||
settings and the game starts once every invitee has accepted — any decline cancels it, and an unanswered invitation
|
||||
expires after seven days.
|
||||
|
||||
### Playing a game *(Stage 3)*
|
||||
### Playing a game
|
||||
Place tiles, pass, exchange, or resign. A play is validated against the game's
|
||||
dictionary at submit time and scored; an unlimited preview reports what a
|
||||
tentative move would score and whether it is legal. The dictionary check tool is
|
||||
@@ -111,7 +110,7 @@ and restored on return (including on another device); a player may **arrange til
|
||||
the opponent's turn**, but that draft is position-only — the score preview and submission
|
||||
stay available only on the player's own turn.
|
||||
|
||||
### Robot opponent *(Stage 5)*
|
||||
### Robot opponent
|
||||
When auto-match finds no human within ten seconds, a robot opponent takes the empty
|
||||
seat so the game starts without waiting. It is meant to feel like a person: it
|
||||
decides once per game whether to play to win (about 40% of the time, so the human
|
||||
@@ -123,7 +122,7 @@ carries a human-like, language-appropriate name (a Russian game draws mostly Rus
|
||||
names); it does not chat, and **silently ignores friend requests** — a request to a
|
||||
robot stays pending and expires, exactly like a human who never responds.
|
||||
|
||||
### Social: friends, block, chat, nudge *(Stage 4 / 8)*
|
||||
### Social: friends, block, chat, nudge
|
||||
Become friends in two ways: redeem a **one-time code** the other player issues (six
|
||||
digits, valid for twelve hours), or send a **request to someone you have played
|
||||
with** — they accept, ignore it (a request lapses after thirty days and can then be
|
||||
@@ -132,7 +131,7 @@ a code). Cancelling your own pending request withdraws it; unfriending removes t
|
||||
friendship. In a game, an **add to friends** item for each opponent mirrors the live
|
||||
relationship: it reads *request sent* (disabled) while a request is pending or was
|
||||
declined, and *in friends* once accepted — updating in place the moment the opponent
|
||||
answers, and staying correct across reloads (Stage 17). Block globally — switch off incoming chat
|
||||
answers, and staying correct across reloads. Block globally — switch off incoming chat
|
||||
and/or friend requests — and block individual players (a per-user block hides that
|
||||
person's chat and stops requests and game invitations both ways; it also ends any
|
||||
existing friendship). Per-game chat is for quick reactions: messages are short
|
||||
@@ -142,16 +141,16 @@ nudge is part of the game chat); the out-of-app push is delivered via the platfo
|
||||
Chat and the word-check tool open as their **own screens** (with a back to the game), and a
|
||||
new chat message raises an **unread badge** on the game's menu until the chat is opened.
|
||||
|
||||
### Profile & settings *(Stage 4 / 8)*
|
||||
### Profile & settings
|
||||
Edit the display name (letters joined by a single space / "." / "_" separator, with an
|
||||
optional trailing ".", up to 32 characters and at most 5 special characters — the "." / "_"
|
||||
punctuation, spaces aside), the timezone (chosen as a UTC offset), the
|
||||
daily away window (on a 10-minute grid, at most 12 hours, wrapping midnight) and the
|
||||
block toggles. The profile form is edited inline (no separate edit mode). Linking
|
||||
an email or Telegram and merging accounts are covered under "Accounts, linking &
|
||||
merge" (Stage 11).
|
||||
merge".
|
||||
|
||||
### History & statistics *(Stage 3 / 8)*
|
||||
### History & statistics
|
||||
Finished games are archived in a dictionary-independent form and exportable to
|
||||
GCG; the export is offered **only once a game is finished** (exporting a live game
|
||||
would leak the move journal), and the client shares the `.gcg` file where the
|
||||
@@ -159,7 +158,7 @@ platform supports it, otherwise downloads it. Statistics (durable accounts only)
|
||||
wins, losses, draws, max points in a game, and max points for a single move (the
|
||||
best play, which already includes every word it formed plus the all-tiles bonus).
|
||||
|
||||
### Administration *(Stage 10)*
|
||||
### Administration
|
||||
Operators reach a server-rendered admin console at `${DOMAIN}/_gm` — the backend
|
||||
renders it; the gateway gates it with HTTP Basic Auth on its public listener and
|
||||
proxies it verbatim. The console lists and inspects **users** (profile, statistics,
|
||||
@@ -173,7 +172,7 @@ applied after a reload). When a Telegram connector is configured an operator can
|
||||
State-changing actions are protected by a same-origin check; the console tracks no
|
||||
operator identity.
|
||||
|
||||
The console also surfaces **rate-limit abuse** (R3): a **Throttled** page lists the
|
||||
The console also surfaces **rate-limit abuse**: a **Throttled** page lists the
|
||||
recently throttled users/IPs the gateway reported (an in-memory window — it resets on
|
||||
a backend restart) and the accounts currently carrying the soft **high-rate flag**. An
|
||||
account sustaining rejections past a tunable threshold is flagged automatically —
|
||||
|
||||
Reference in New Issue
Block a user