2026-10-14 09:13:52 +03:00
|
|
|
# TODO
|
|
|
|
|
|
|
|
|
|
## Auth
|
|
|
|
|
|
|
|
|
|
### Mobile login with Keycloak (phase 5)
|
|
|
|
|
|
|
|
|
|
The web app logs in with Keycloak; the mobile app still uses the legacy `?userKey=` login.
|
|
|
|
|
|
|
|
|
|
- [ ] Add a `mancala-mobile` public client to `apps/keycloak/realm/mancala-realm.json` (PKCE S256, redirect
|
|
|
|
|
`com.mancala_mobile://callback`) and to `KEYCLOAK_CLIENT_IDS` for the backend
|
|
|
|
|
- [ ] Add `react-native-app-auth` with the redirect scheme set up for Android and iOS
|
|
|
|
|
- [ ] Log in as a guest on first launch (`guest=true`), with `offline_access`; keep tokens in MMKV
|
|
|
|
|
- [ ] Connect with `rtmt.connectWebSocket(url, getToken)` instead of `?userKey=` (`apps/mobile/src/App.tsx`)
|
|
|
|
|
and call `reauthenticate` after refreshing the token
|
|
|
|
|
- [ ] Log in / sign up / log out in the app, player names on the game screen (`getPlayerDisplayName` in core)
|
|
|
|
|
- [ ] Decide whether guests may skip the browser tab on first launch (would need a custom grant type in the
|
|
|
|
|
Keycloak extension)
|
|
|
|
|
- [ ] Delete the unused copy of the WebSocket client in `apps/mobile/src/rtmt`
|
|
|
|
|
- [ ] Test on a device
|
|
|
|
|
|
2026-10-16 00:36:48 +03:00
|
|
|
### Game history on mobile
|
|
|
|
|
|
|
|
|
|
The web app has game history (see `docs/specs/game-history`); the mobile app needs Keycloak login first.
|
|
|
|
|
|
|
|
|
|
- [ ] Ongoing-game banner, live and popular games, recent games on the home screen
|
|
|
|
|
- [ ] Move list and looking back during a live game; replay of finished games
|
|
|
|
|
|
2026-10-14 09:13:52 +03:00
|
|
|
### After the mobile release
|
|
|
|
|
|
|
|
|
|
- [ ] Turn off `LEGACY_USERKEY_AUTH` once old app versions are no longer in use; this also removes `/register`
|
|
|
|
|
|
|
|
|
|
### Later
|
|
|
|
|
|
|
|
|
|
- [ ] Let guests turn their guest user into an account without changing identity (Keycloak required action)
|
2026-10-16 00:36:48 +03:00
|
|
|
- [ ] Statistics for logged in users (wins, losses), now that games are saved
|
2026-10-14 09:13:52 +03:00
|
|
|
- [ ] Social logins (Keycloak identity providers)
|
2026-10-16 01:13:20 +03:00
|
|
|
- [ ] Keycloak email theme in the game's look (password reset emails still use Keycloak's)
|
|
|
|
|
- [ ] Login pages follow the system color scheme; they could follow the theme chosen in the app instead
|
2026-10-14 09:13:52 +03:00
|
|
|
- [ ] Restrict the Keycloak admin console in production
|
|
|
|
|
|
2026-10-16 00:36:48 +03:00
|
|
|
## Game history
|
|
|
|
|
|
|
|
|
|
- [ ] A page with all of a user's games (the home page shows the last 3)
|
|
|
|
|
- [ ] Show games of deleted accounts differently, once accounts can be deleted
|
|
|
|
|
- [ ] Live game state, previews and spectators assume a single backend instance; share them (e.g. Valkey pub/sub)
|
|
|
|
|
before running more than one
|
|
|
|
|
- [ ] If Valkey is unreachable when the backend starts, live games are not restored until the next restart
|
|
|
|
|
|
2026-10-16 01:54:01 +03:00
|
|
|
## Game clock
|
|
|
|
|
|
|
|
|
|
See `docs/specs/game-clock`.
|
|
|
|
|
|
|
|
|
|
- [ ] Other time controls or time added per move; a long move animates on the next player's time
|
|
|
|
|
- [ ] Clocks in the home page's live game previews and in the ongoing-game banner
|
|
|
|
|
- [ ] Try the mobile clocks on a device; only the type check and the bundle were run
|
|
|
|
|
|
2026-10-16 10:26:59 +03:00
|
|
|
## Web redesign
|
|
|
|
|
|
|
|
|
|
See `docs/specs/web-redesign`.
|
|
|
|
|
|
|
|
|
|
- [ ] Bring the new design to the mobile app (themes, board, game screen)
|
|
|
|
|
- [ ] A rematch button on the game-over card (the design has one; there is no rematch yet)
|
|
|
|
|
|
2026-10-14 09:13:52 +03:00
|
|
|
## Deployment
|
|
|
|
|
|
|
|
|
|
- [ ] Build the backend and frontend images from the repo root in CI:
|
|
|
|
|
`docker build -f apps/backend/Dockerfile .` and `docker build -f apps/frontend/Dockerfile .`
|
|
|
|
|
- [ ] Pass `--build-arg KEYCLOAK_URL=https://auth.playmancala.app` when building the frontend image
|
|
|
|
|
- [ ] Deploy Keycloak (`apps/.env` with `KEYCLOAK_DB_PASSWORD`, `KEYCLOAK_ADMIN_PASSWORD`,
|
|
|
|
|
`KEYCLOAK_HOSTNAME=https://auth.playmancala.app`) and reload nginx with the new `auth.playmancala.app` block
|
|
|
|
|
- [ ] Deploy the backend before the web app; the new web app needs token auth on the server
|
2026-10-16 11:53:13 +03:00
|
|
|
- [ ] The backend is now Java (Quarkus, see `docs/specs/quarkus-backend`); the compose file passes the database as
|
|
|
|
|
`DATABASE_JDBC_URL`/`DATABASE_USERNAME`/`DATABASE_PASSWORD` built from the same `MANCALA_DB_PASSWORD`, so
|
|
|
|
|
`apps/.env` needs no change. It reads the Node backend's database and live games, so it can replace it (and be
|
|
|
|
|
rolled back) without ending games
|
2026-10-16 01:54:01 +03:00
|
|
|
- [ ] Release the mobile update with the game clock before or with the backend: older app versions do not show the
|
|
|
|
|
clock and do not handle `on_game_end`, so a game they lose on time does not end for them
|
2026-10-16 00:36:48 +03:00
|
|
|
- [ ] Back up the Postgres volume (Keycloak and saved games), e.g. a daily `pg_dumpall`
|
|
|
|
|
- [ ] Set `MANCALA_DB_PASSWORD` and `POSTGRES_PASSWORD` in `apps/.env` on the server; the `postgres` volume replaces
|
|
|
|
|
`keycloak-db`, so Keycloak starts with a fresh database there
|
2026-10-16 10:52:15 +03:00
|
|
|
- [ ] Last step: publish a new `mancala.js` to npm (it is at `0.0.2-beta.3` from 2022), so the published engine skips
|
|
|
|
|
the opponent's store when sowing. The apps do not need it; they use `packages/mancala.js` through `link:`
|
2026-10-14 09:13:52 +03:00
|
|
|
|
|
|
|
|
## Security
|
|
|
|
|
|
|
|
|
|
- [ ] Move the Android signing passwords out of `apps/mobile/release_android.sh` (committed in `bb1c750`) into
|
|
|
|
|
`~/.gradle/gradle.properties` or environment variables, and consider resetting the upload key
|
|
|
|
|
- [ ] Add `apps/mobile/mancala-upload-key.jks` to `.gitignore` (only `android/app/mancala-upload-key.jks` is ignored)
|
|
|
|
|
- [ ] Validate moves before running them instead of treating every invalid move as a crash: each one writes a
|
2026-10-16 11:53:13 +03:00
|
|
|
file to `crashes/` and is broadcast to the players (`GameManager.onGameError`, kept as it was in the Node
|
|
|
|
|
backend)
|
2026-10-14 09:13:52 +03:00
|
|
|
|
2026-10-16 10:49:29 +03:00
|
|
|
## Game rules
|
|
|
|
|
|
|
|
|
|
- [ ] Decide who gets the remaining stones when a move empties the opponent's side (e.g. a capture takes their last
|
|
|
|
|
stones). Now the player whose side is empty always gets the other side's stones (`GRClearBoardAtEnd`), even
|
|
|
|
|
when the opponent emptied it; some Mangala rules give them only to a player who emptied their own side.
|
|
|
|
|
Analyse the rule first, then decide
|
|
|
|
|
|
2026-10-14 09:13:52 +03:00
|
|
|
## Bugs
|
|
|
|
|
|
|
|
|
|
- [ ] `PitAnimator.dispose` removes a newly bound function, so the theme listener is never removed
|
2026-10-16 11:53:13 +03:00
|
|
|
- [ ] `onGameError` broadcasts `{}` instead of the error (the Java backend sends `{}` on purpose, as the Node backend
|
|
|
|
|
did)
|
2026-10-14 09:13:52 +03:00
|
|
|
|
|
|
|
|
## Maintenance
|
|
|
|
|
|
|
|
|
|
- [ ] The web and mobile apps duplicate components and stores; move shared code into `packages/core`
|
|
|
|
|
- [ ] Mixed lockfiles: `packages/*` and `apps/mobile` have both `yarn.lock` and `package-lock.json`
|
|
|
|
|
- [ ] Align TypeScript and Jest versions across packages
|
2026-10-16 10:49:29 +03:00
|
|
|
- [ ] Tests for `MatchMaker`; `PitAnimator` is only tested for the first frame of a move
|
2026-10-16 11:53:13 +03:00
|
|
|
- [ ] CI that runs the tests (the backend's need a JDK 25 and Docker)
|
|
|
|
|
- [ ] The rules exist twice, in `packages/mancala.js` and in the backend's Java port; a parity test keeps them alike,
|
|
|
|
|
but every rule change has to be made in both
|
2026-10-14 09:13:52 +03:00
|
|
|
- [ ] Pre-existing type errors: 4 in the frontend, 11 in mobile; the frontend has no `tsconfig.json`, so nothing
|
|
|
|
|
type-checks it
|