AGENTS.md notes on the themes, plain CSS for container queries and driving the app in Chrome; TODO.md gets the mobile app and rematch as open work; the spec is marked implemented.
5.1 KiB
5.1 KiB
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-mobilepublic client toapps/keycloak/realm/mancala-realm.json(PKCE S256, redirectcom.mancala_mobile://callback) and toKEYCLOAK_CLIENT_IDSfor the backend - Add
react-native-app-authwith the redirect scheme set up for Android and iOS - Log in as a guest on first launch (
guest=true), withoffline_access; keep tokens in MMKV - Connect with
rtmt.connectWebSocket(url, getToken)instead of?userKey=(apps/mobile/src/App.tsx) and callreauthenticateafter refreshing the token - Log in / sign up / log out in the app, player names on the game screen (
getPlayerDisplayNamein 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
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
After the mobile release
- Turn off
LEGACY_USERKEY_AUTHonce 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)
- Statistics for logged in users (wins, losses), now that games are saved
- Social logins (Keycloak identity providers)
- Restrict the Keycloak admin console in production
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
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
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)
Deployment
- Build the backend and frontend images from the repo root in CI:
docker build -f apps/backend/Dockerfile .anddocker build -f apps/frontend/Dockerfile . - Pass
--build-arg KEYCLOAK_URL=https://auth.playmancala.appwhen building the frontend image - Deploy Keycloak (
apps/.envwithKEYCLOAK_DB_PASSWORD,KEYCLOAK_ADMIN_PASSWORD,KEYCLOAK_HOSTNAME=https://auth.playmancala.app) and reload nginx with the newauth.playmancala.appblock - Deploy the backend before the web app; the new web app needs token auth on the server
- 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 - Back up the Postgres volume (Keycloak and saved games), e.g. a daily
pg_dumpall - Set
MANCALA_DB_PASSWORDandPOSTGRES_PASSWORDinapps/.envon the server; thepostgresvolume replaceskeycloak-db, so Keycloak starts with a fresh database there
Security
- Move the Android signing passwords out of
apps/mobile/release_android.sh(committed inbb1c750) into~/.gradle/gradle.propertiesor environment variables, and consider resetting the upload key - Add
apps/mobile/mancala-upload-key.jksto.gitignore(onlyandroid/app/mancala-upload-key.jksis 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
PitAnimator.animatePit:previousPitIndex > 0should be>= 0; a one-stone move from pit 0 does not empty that pit during the animationPitAnimator.disposeremoves 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
onGameErrorbroadcasts anError, which serializes to{}
Maintenance
- The web and mobile apps duplicate components and stores; move shared code into
packages/core - Mixed lockfiles:
packages/*andapps/mobilehave bothyarn.lockandpackage-lock.json - Align TypeScript and Jest versions across packages
- Tests for
MatchMakerandPitAnimator - 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