effe6675bc
Tests · Go / test (push) Successful in 32s
- go.work (Go 1.26.3) with backend module; deps added incrementally (gin+zap only) - backend: /healthz + /readyz, env config, graceful shutdown - docs: ARCHITECTURE, FUNCTIONAL (+ru mirror), TESTING - PLAN.md (stage tracker + per-stage open details) and CLAUDE.md (per-stage workflow) - .gitea go-unit CI (gofmt/vet/build/test)
153 lines
7.8 KiB
Markdown
153 lines
7.8 KiB
Markdown
# Scrabble Game — implementation plan
|
||
|
||
Living plan and **stage tracker**. Each stage is implemented in its own session;
|
||
the rules for starting and finishing a stage are in [`CLAUDE.md`](CLAUDE.md).
|
||
The architecture/decision record is [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md);
|
||
behaviour is [`docs/FUNCTIONAL.md`](docs/FUNCTIONAL.md). When a stage produces a
|
||
decision, bake it back here **and** into the affected docs/code in the same PR.
|
||
|
||
## Context
|
||
|
||
Greenfield multiplatform Scrabble. Players arrive from a platform (Telegram
|
||
first; later VK/MAX/iOS/Android) or standalone web (email / guest). Three
|
||
executables — `gateway`, `backend`, `ui` — plus per-platform side-services.
|
||
Deliberately simpler than the sibling `../galaxy-game` (idea donor, not a
|
||
template). The `../scrabble-solver` engine is embedded in-process as a library.
|
||
|
||
## Locked decisions (recap — full record in docs/ARCHITECTURE.md)
|
||
|
||
Stack: `go.work` monorepo, modules `scrabble/<name>`, Go 1.26.x, backend
|
||
gin+pgx+Postgres(schema `backend`)+goose+zap+OTel (deps added when first used).
|
||
Wire: Connect-RPC + FlatBuffers (client↔gateway), REST/JSON + `X-User-ID`
|
||
(gateway↔backend), gRPC server-stream for live events. Auth: platform-native,
|
||
thin opaque session token, no Ed25519/signing, likely no Redis. UI: pure
|
||
HTML5/CSS, plain Svelte + Vite, Capacitor for native. MVP surfaces: Telegram +
|
||
web (email + ephemeral guest) + link/merge. Variants: ru/en/Эрудит.
|
||
Legality: validate-at-submit. End: empty bag+rack / 6 scoreless / 24h timeout.
|
||
Hint: top-1. Word-check: unlimited + complaint. Robot: P(win)≈0.40, margin
|
||
targeting, [2,90]min skewed timing, sleep 00:00–07:00 opp-tz, nudge logic.
|
||
Dictionary: pin per game. History: structured + GCG export, dictionary-
|
||
independent (see ARCHITECTURE §9.1).
|
||
|
||
## Stage tracker
|
||
|
||
| # | Stage | Status |
|
||
|---|-------|--------|
|
||
| 0 | Scaffolding (go.work, backend skeleton, docs, CI) | **in review (CI)** |
|
||
| 1 | Backend foundation (config, server, Postgres+goose, sessions, accounts) | todo |
|
||
| 2 | Engine package over scrabble-solver | todo |
|
||
| 3 | Game domain (lifecycle, rules, hint, word-check, history+GCG, stats) | todo |
|
||
| 4 | Lobby & social (matchmaking, friends, block, chat, profile, nudge) | todo |
|
||
| 5 | Robot opponent | todo |
|
||
| 6 | Gateway edge (Connect/FB, platform auth, sessions, push bridge, admin) | todo |
|
||
| 7 | UI (plain Svelte + Vite, board, lobby, chat, i18n) | todo |
|
||
| 8 | Telegram integration (bot side-service, deep-link, push) | todo |
|
||
| 9 | Admin & dictionary ops (complaint review, version reload) | todo |
|
||
| 10 | Account linking & merge | todo |
|
||
| 11 | Polish (observability, perf with evidence, deploy) | todo |
|
||
|
||
Scaffolding is incremental: `go.work` lists only existing modules; each stage
|
||
adds the modules it needs.
|
||
|
||
## Stages
|
||
|
||
Each stage: read this plan + relevant docs, **interview the owner on the open
|
||
details below**, implement within scope, then update plan/docs/code and get CI
|
||
green before marking done.
|
||
|
||
### Stage 0 — Scaffolding *(in review)*
|
||
Scope: `go.work` (Go 1.26.3, `use ./backend`); minimal runnable `backend`
|
||
(gin, zap, `/healthz`, `/readyz`, env config); docs skeleton; `PLAN.md`;
|
||
`CLAUDE.md`; `.gitea/workflows/go-unit.yaml`; README; `.gitignore`.
|
||
Acceptance: `go build ./backend/...` + `go vet` + gofmt clean +
|
||
`go test ./backend/...` green; CI green on push.
|
||
|
||
### Stage 1 — Backend foundation
|
||
Scope: config/server route groups (`/api/v1/{public,user,internal,admin}`,
|
||
probes), Postgres (pgx) + embedded goose migrations + schema `backend`,
|
||
telemetry (OTel) wiring, in-memory cache scaffolding, thin sessions + accounts +
|
||
platform identities.
|
||
Open details: Postgres version + DSN/`search_path` convention; jet vs
|
||
sqlc/sqlx (default jet); migration naming; exact session-token shape (opaque
|
||
random length, TTL, revocation); account/identity table shape; whether the
|
||
admin bootstrap lands here or in Stage 9.
|
||
|
||
### Stage 2 — Engine package
|
||
Scope: `backend/internal/engine` over scrabble-solver — versioned DAWG
|
||
load/registry, GenerateMoves/ValidatePlay/ScorePlay wrappers, bag/rack, the
|
||
**dictionary-independent** game-state model + decode helpers. Add
|
||
`replace scrabble-solver => ../scrabble-solver` to `go.work` here and solve the
|
||
CI sibling-checkout (clone `gitea.iliadenisov.ru/.../scrabble-solver`).
|
||
Open details: how CI obtains the solver (clone sibling vs publish/tag the
|
||
solver module); in-memory game-state representation; how blanks and exchanges
|
||
are modelled; Эрудит specifics to verify against the solver.
|
||
|
||
### Stage 3 — Game domain
|
||
Scope: create/join, turn order, submit play/pass/exchange/resign,
|
||
validate-at-submit, scoring, end-conditions, 24h timeout/auto-resign, hint,
|
||
word-check + complaint capture, structured history + GCG writer, stats on
|
||
finish.
|
||
Open details: GCG dialect details (blanks, exchanges, notation); exact stats
|
||
edge cases; turn-timeout scheduler mechanism (cron vs per-game timer);
|
||
complaint payload shape.
|
||
|
||
### Stage 4 — Lobby & social
|
||
Scope: matchmaking pool, friends, block, per-game chat, profile + email
|
||
confirm-code, nudge.
|
||
Open details: pool fairness/keying confirmation; deep-link format per platform;
|
||
chat length limit + retention; friend-request lifecycle; email-code provider
|
||
(SMTP relay choice).
|
||
|
||
### Stage 5 — Robot opponent
|
||
Scope: human-like player — balance ~0.40, margin targeting, skewed [2,90]min
|
||
timing + sleep + nudge logic, friend/DM blocking, name pool.
|
||
Open details: exact delay distribution + parameters; margin band; name pool
|
||
source; how the scheduler drives robot moves; metrics for tuning balance.
|
||
|
||
### Stage 6 — Gateway edge
|
||
Scope: Connect/gRPC-Web (h2c), Telegram initData validation → session →
|
||
`X-User-ID`, in-memory rate-limit, admin Basic-Auth passthrough, FlatBuffers
|
||
transcoding, in-app push stream bridging backend `push` gRPC stream, email +
|
||
ephemeral-guest paths.
|
||
Open details: FlatBuffers schema layout + message_type catalog; rate-limit
|
||
classes/limits; admin surface routing; session cache shape at the gateway.
|
||
|
||
### Stage 7 — UI
|
||
Scope: plain Svelte + Vite static; Connect-web + FlatBuffers client; lobby (my
|
||
games, profile tabs); board (HTML5/CSS grid, drag-n-drop, no assets); chat;
|
||
hint/word-check; in-app stream; i18n en/ru; in-memory session (+IndexedDB if
|
||
available); Capacitor-ready structure.
|
||
Open details: detailed game-board UX (deferred by the owner to this stage);
|
||
client routing; offline/refresh behaviour; design system / theming.
|
||
|
||
### Stage 8 — Telegram integration
|
||
Scope: bot side-service, deep-link invites, platform push (your-turn / nudge),
|
||
Mini App launch/auth; backend↔platform internal API.
|
||
Open details: bot framework/library; deep-link scheme; push message templates;
|
||
internal API contract; Mini App hosting/origin.
|
||
|
||
### Stage 9 — Admin & dictionary ops
|
||
Scope: admin endpoints (users, games, complaint review queue, dictionary
|
||
versions + reload), complaint→dictionary update pipeline.
|
||
Open details: whether a server-rendered console is wanted or JSON-only; the
|
||
dictionary rebuild/deploy pipeline; complaint resolution workflow.
|
||
|
||
### Stage 10 — Account linking & merge
|
||
Scope: link-via-confirm; merge-into-A (stats sum, transfer games/friends,
|
||
dedupe). High blast-radius — focused regression tests.
|
||
Open details: conflict resolution (active games on both, duplicate friends,
|
||
display-name collisions); irreversibility/audit; confirm-flow per platform.
|
||
|
||
### Stage 11 — Polish
|
||
Scope: observability dashboards, evidence-based performance work, prod
|
||
build/deploy.
|
||
Open details: deployment target/host; dashboards; load expectations.
|
||
|
||
## Refinements logged during implementation
|
||
|
||
- **Stage 0**: solver `replace` deferred to Stage 2 (nothing imports it yet;
|
||
adding the path now would break CI, which checks out only this repo). Docker /
|
||
compose deferred to a stage that has something to deploy. Trunk is `master`
|
||
(owner preference); `feature/*` + PR from Stage 1; the genesis commit lands on
|
||
`master` by necessity.
|