# Mancala Backend This is the backend code for the Mancala project, written in Express.js. ## Getting Started ### Install Packages ```bash yarn install ``` ### Start in Development Mode ```bash yarn dev ``` ### Start in Release Mode ```bash yarn build yarn start ``` ### Development Dependencies This package links the local packages `@mancala/core` and `mancala.js`. Build them first with `yarn build:packages` in the repo root. ## Authentication Clients log in with Keycloak (see `apps/keycloak`), either as a guest or with an account, and send the access token over the WebSocket right after connecting: ```json { "channel": "auth", "message": { "token": "" } } ``` The server answers on `on_auth` with the user (`{ id, name, isGuest }`) or on `on_auth_error` and closes the socket with code 4001. Other messages are ignored until the socket is authenticated, and connections that do not authenticate within 5 seconds are closed. Send `auth` again with the new token after refreshing it. User ids of Keycloak users are the token subject prefixed with `kc:`. | Variable | Default | Purpose | |---|---|---| | `KEYCLOAK_ISSUER` | `http://localhost:8080/realms/mancala` | Token issuer; must match the `iss` claim exactly | | `KEYCLOAK_JWKS_URL` | issuer + `/protocol/openid-connect/certs` | Where to fetch signing keys, if the backend reaches Keycloak at a different address | | `KEYCLOAK_CLIENT_IDS` | `mancala-web` | Comma-separated clients whose tokens are accepted | | `LEGACY_USERKEY_AUTH` | `true` | Also accept old clients that connect with `?userKey=` and the `/register` endpoint. Turn off once no released client uses it, because a userKey is not a secret the server can check | ## Saved games and live games Finished games are saved in Postgres; live games are copied to Valkey after every change and restored when the backend starts, so a restart or deploy does not end them. The design is in `docs/specs/game-history`. | Variable | Default | Purpose | |---|---|---| | `DATABASE_URL` | `postgres://mancala:mancala@localhost:5433/mancala` | Saved games; migrations run on startup | | `VALKEY_URL` | `redis://localhost:6379` | Live game state and short-lived caches | The backend keeps running when either is down: games are still played, finished games are saved once Postgres is back, and lists are served without the missing data. | Route | Auth | Response | |---|---|---| | `GET /game/:id` | – | A live game, or `{ status: "finished", record }` | | `GET /games/popular?limit=5` | – | `{ kind: "live" \| "finished", games }` | | `GET /games/me/active` | Bearer token | `{ game }` or `{ game: null }` | | `GET /games/me?limit=3` | Bearer token | `{ games }`, newest first | Tests use Docker (testcontainers) for Postgres and Valkey.