From 20efa40e6cabb7f0f6dc170a1bca3f8dbf36fd55 Mon Sep 17 00:00:00 2001 From: Halit Aksoy Date: Wed, 14 Oct 2026 09:13:52 +0300 Subject: [PATCH] docs: add TODO with mobile login and open issues --- TODO.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..aee924a --- /dev/null +++ b/TODO.md @@ -0,0 +1,71 @@ +# 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 + +### 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) +- [ ] Stats and game history for logged in users (needs a database) +- [ ] Social logins (Keycloak identity providers) +- [ ] Restrict the Keycloak admin console in production + +## 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 + +## 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 + file to `crashes/` and is broadcast to the players (`GameManager.onGameError`) + +## Bugs + +- [ ] `GameStoreImpl.getSpeactatingGameIdsByUser` loops with `for...in` over an iterator, so it never finds + anything and spectators are never removed on disconnect; use `for...of` +- [ ] Finished and abandoned games are never removed from `gameStore` (`deleteGame` only removes the user + mappings), so they stay in memory until restart +- [ ] `PitAnimator.animatePit`: `previousPitIndex > 0` should be `>= 0`; a one-stone move from pit 0 does not + empty that pit during the animation +- [ ] `PitAnimator.dispose` removes a newly bound function, so the theme listener is never removed +- [ ] Sowing puts stones into the opponent's store; check against the intended Mangala rules and add a test +- [ ] `MatchMaker.join` does not check whether the player is already in a game +- [ ] `GameManager.startGame` sends the connection info twice +- [ ] `onGameError` broadcasts an `Error`, which serializes to `{}` + +## 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 +- [ ] Tests for `GameManager`, `MatchMaker` and `PitAnimator` +- [ ] CI that runs the tests +- [ ] Pre-existing type errors: 4 in the frontend, 11 in mobile; the frontend has no `tsconfig.json`, so nothing + type-checks it