-
Mahmoud Aglan authored
Found while building the org/redeem layer; all exploitable with the public anon key that ships in realtime.js, or with a player's own session. - complete_match, award_coins and the match/queue functions were executable by anon and players: one REST call paid win coins to anyone. Service role only now; every caller is PHP with the service key. - battlepass.php credited whatever "coins" the request carried, to anyone, as often as asked. The server now decides the reward, needs an active season and an unlocked tier, and pays each tier once. - The legacy api/ludo.php let any player end any ludo match with any winners and get paid. It, api/domino.php and api/multiplayer.php were unused by the app and are removed. - Shop, challenges and daily reward wrote balances with the player's token, which only worked because players could PATCH their own coins over REST. They write with the service key now; the shop deducts only if the balance is unchanged (a double tap cannot pay twice), refunds if the grant fails, and records its transaction (the old insert used a missing column). - Policies: anyone could delete any ludo/domino/backgammon match, rewrite queues, groups and the theme, insert an "accepted" friendship with anyone and post into any chat. Writes are service-role only; every read and Realtime feed is unchanged. Group members read only their own memberships. - profiles-guard.sql (applied after this deploy): a player's token may change only cosmetic profile fields. Also the org-unify / redeem SQL layer and its contract (docs/redeem-contract.md). Co-Authored-By:Claude Opus 5.5 <noreply@anthropic.com>
f4eec81f