# scrabble-game

Multiplatform Scrabble game. Players arrive from a platform (Telegram first;
later VK/MAX/iOS/Android) or from standalone web (email / guest). The game
supports English Scrabble, Russian Scrabble and Эрудит.

## Components

- **`gateway`** — the only public ingress: anti-abuse, platform authentication
  (resolves the player and injects `X-User-ID`), routing to `backend`, and an
  admin surface behind Basic Auth.
- **`backend`** — internal-only service that owns every domain concern and
  embeds the [`scrabble-solver`](../scrabble-solver) engine library in-process.
- **`ui`** — pure-HTML5 client (plain Svelte 5 + TypeScript + Vite) over Connect-RPC
  + FlatBuffers, embeddable in platform webviews and packageable to native via
  Capacitor. See [`ui/README.md`](ui/README.md).
- **`platform/*`** — per-platform side-services (e.g. the Telegram bot).

## Documentation (sources of truth)

- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — global architecture, transport,
  security, cross-service contracts.
- [`docs/FUNCTIONAL.md`](docs/FUNCTIONAL.md) (+ [`_ru`](docs/FUNCTIONAL_ru.md)) —
  per-domain user stories.
- [`docs/TESTING.md`](docs/TESTING.md) — test layers and the CI gate.
- [`CLAUDE.md`](CLAUDE.md) — project guide and development workflow.

## Build & test

```sh
go build ./backend/... ./pkg/... ./gateway/...  # per module (the workspace spans several)
go vet ./backend/... ./pkg/... ./gateway/...
gofmt -l .                                       # must print nothing
go test -count=1 ./backend/... ./pkg/... ./gateway/...   # unit tests
go test -tags=integration -count=1 -p=1 ./backend/...    # + Postgres (needs Docker)
```

The `integration`-tagged tests start a throwaway `postgres:17-alpine` container
via testcontainers-go and require a reachable Docker daemon; they live in the
`backend` module. The wire contracts in `pkg` and the Connect edge in `gateway`
have committed generated code (regenerate dev-time with `make -C pkg gen` /
`make -C gateway gen`).

## Run the backend locally

The backend now owns persistence, so it needs Postgres and applies its embedded
migrations at startup:

```sh
docker run -d --name scrabble-pg -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres:17-alpine
BACKEND_POSTGRES_DSN='postgres://postgres:dev@localhost:5432/postgres?search_path=backend&sslmode=disable' \
  go run ./backend/cmd/backend     # HTTP API + probes on :8080, push gRPC on :9090
```

## Run the gateway locally

The gateway is the public edge; point it at a running backend:

```sh
GATEWAY_BACKEND_HTTP_URL=http://localhost:8080 \
GATEWAY_BACKEND_GRPC_ADDR=localhost:9090 \
  go run ./gateway/cmd/gateway     # Connect/h2c edge on :8081
```

Key environment: `BACKEND_HTTP_ADDR` (default `:8080`), `BACKEND_LOG_LEVEL`
(`debug|info|warn|error`, default `info`), `BACKEND_POSTGRES_DSN` (**required**).
The full configuration surface and the go-jet regeneration step live in
[`backend/README.md`](backend/README.md).

## Run the UI locally

```sh
cd ui && pnpm install
pnpm start     # mock mode: lobby -> game with no backend, on http://localhost:5173
pnpm dev       # against a running gateway (Vite proxies the RPC path to :8081)
```

`pnpm check` (type-check), `pnpm test:unit` (Vitest), `pnpm test:e2e` (Playwright
smoke vs the mock), `pnpm build` (static bundle). Details — including the committed
edge codegen (`pnpm codegen`) — are in [`ui/README.md`](ui/README.md).

## Deploy (`deploy/`)

The full contour is [`deploy/docker-compose.yml`](deploy/docker-compose.yml):
`backend` + `gateway` (with the UI embedded via `go:embed`, baked in by its node
build stage) + Postgres + the Telegram connector (with a VPN sidecar) + an
observability stack (OTel Collector → Prometheus + Tempo → Grafana) + a front
**caddy** that owns a single `/_gm` Basic-Auth (admin console + Grafana). The Go
services build from multi-stage distroless `*/Dockerfile`.

```sh
docker build --build-arg DICT_VERSION=v1.3.0 -f backend/Dockerfile -t scrabble-backend .  # DICT_VERSION required; pulls that DAWG release artifact
docker build -f gateway/Dockerfile -t scrabble-gateway .   # node stage builds + embeds the UI
docker compose -f deploy/docker-compose.yml config         # validate (needs the TEST_/PROD_ env)
```

CI auto-deploys the **test contour** on a PR into — or push to — `development`
(`.gitea/workflows/ci.yaml`); the **prod contour** is a manual deploy after
`development → master`. Env reference: [`deploy/.env.example`](deploy/.env.example);
the topology and the two-contour model are in
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §13.
