Files
CaseGambling/amelioration.md
T
2026-07-25 20:04:34 +02:00

10 KiB
Raw Blame History

CaseOrion — Analyse & améliorations

Date : 2026-07-25
Périmètre : analyse complète (server + client + Docker), sans modification de code.
Stack : Express / Prisma / SQLite / Socket.IO · React (Vite) · ~16k LOC client+server.


Synthèse

Le projet est une API jeu cohérente en mono-process, avec un effort sérieux sur l’économie haute (crédits en strings + BigInt via cents.js).
Les risques les plus graves sont : odds duel cassées, paiements mock en prod, db push --accept-data-loss au boot, comparaisons argent via Number(), et état in-memory (sessions, timers battles, présence).

Zone État
Cases / wear / keys Solide (roll serveur, BigInt value)
Auto-sell Logique OK (value < seuil) ; UX/confusion catalogue vs instance
Jackpot / Battle Agrégation BigInt correcte
Duels 1vX Supprimé (2026-07-25)
Vault / prestige Fonctionnel ; settle concurrent risqué
Shop Mock OK en dev ; dangereux si prod
Docker Marche en single-node ; pas scale-ready

P0 — Critique (corriger en premier)

1. Odds des duels faussées (multi-items)résolu par suppression

Le mode 1vX Case (rooms custom / duel.js) a été retiré (2026-07-25). Il ne reste que le Battle MultiPlayers (jackpot.js). Les anciennes routes /battle/1vx redirigent vers /battle.

1. Paiements mock utilisables en production

Fichiers : server/src/payments.js, routes/shop.js, .env.prod.example

PAYMENTS_PROVIDER=mock + POST /api/shop/osu/confirm crédite losu sans paiement.

Proposition Détail
A Refuser mock si NODE_ENV=production sauf ALLOW_MOCK_PAYMENTS=1
B Brancher Stripe (webhook raw body + signature)
C Désactiver toute la section osu en prod tant que non prêt

3. prisma db push --accept-data-loss à chaque démarrage Docker

Fichiers : Dockerfile, docker-compose.yml

Peut détruire / tronquer des colonnes au restart. Inadapté à une vraie prod.

Proposition Détail
A (recommandé) Prisma Migrate (migrate deploy) ; push manuel hors boot
B Garder push sans --accept-data-loss + fail loud
C Job one-shot de migration séparé du CMD app

4. db.js coerce tous les BigInt → Numbercorrigé

reviveMoney supprimé. Choix retenu : argent en strings + toCentsBigInt (pas de plafond Number), BigInt Prisma éventuels laissés intacts jusquau JSON (toString dans index.js). Pas de conversion globale silencieuse.


5. Uploads SVG → XSS stockécorrigé

Allowlist PNG / JPEG / WebP / GIF (MIME + extension + vérif sharp du format réel). SVG et autres image/* refusés (admin + avatar).


P1 — Économie & précision (haute priorité)

6. Finir la migration argent BigInt-safe (bout en bout)corrigé (A)

Helpers client dans api.js : toCentsBigInt, compareCents, centsJson (miroir serveur). Branchés sur ItemTile, CasePage, Dashboard, Battle, Prestige shortfall, Admin sorts/inputs. Affichage via les mêmes helpers.


7. Courses sur le solde (TOCTOU)corrigé (A)

spendUserBalance / creditUserBalance / adjustUserBalance dans cents.js : update SQL atomique balance = balance ± x WHERE balance >= cost (INTEGER SQLite) ou CAS string pour montants > Int64. Branché open case, prestige, sell/auto-sell, vault, shop, jackpot.

Même famille restante : double settle vault (login + socket + intervalle) — le crédit est atomique, mais le calcul de ticks peut encore se chevaucher.


8. Auto-sell — clarté & robustessepartiel (A)

Won banner case : toujours wear + valeur dinstance ; si auto-sold, ajoute aussi le payout.

Reste ouvert : B immédiat serveur · C TTL claim · D confirm prestige.


9. Colonnes prestige mortes / non branchéescorrigé (B)

Supprimées du schema + reset server-prestige : prestigeKeyOpenReduction, prestigeStartBonus, prestigeAdBonus, prestigeAdCooldownReduction, prestigeShopDiscount, prestigeStartOsu, prestigeDropValueBonus, prestigeCaseDiscount.


P2 — Sécurité & prod

10. Sessions MemoryStore

Perdues au restart ; incompatible multi-replicas.

| Proposition | A : SQLite/Redis store · B : sticky single node documenté · C : JWT (changement plus large) |

11. CORS trop permissif

index.js autorise toujours localhost + LAN HTTP, même “prod”.

| Proposition | A : en prod, uniquement CLIENT_ORIGIN + CORS_ORIGINS |

12. Rate limiting absent

Login / register / open / ad / shop confirm non limités.

| Proposition | A : express-rate-limit par IP+user · B : captcha register · C : cooldowns serveur déjà partiels (ad) à généraliser |

13. Admin via session.role sans re-check DB

Élévation stale possible.

| Proposition | A : requireAdmin recharge le user · B : claim roleVersion en session |

14. Secrets & config

SESSION_SECRET=dev-secret par défaut ; pas de server/.env.example local (seulement README + .env.prod.example).

| Proposition | A : fail boot si secret faible en prod · B : ajouter .env.example |

15. Mots de passe faibles

Min 6 caractères seulement.

| Proposition | A : min 8 + zxcvbn soft · B : garder simple (jeu privé) mais documenter |


P3 — Qualité code / refactor

16. Duplication jackpot ↔ duel

Serialize, finish spin, auto-sell winner : quasi copy-paste.

| Proposition | A : module services/battleCommon.js · B : unifier modèle “room” (plus gros refactor) |

17. serializeInv dupliqué

inventory.js / profile.js (et variantes).

| Proposition | A : serializeInventoryItem partagé |

18. Client — listeners socket.on('connect') jamais retirés

Layout, BattleHub, BattleRoom, Duel*, DropFeed → fuite de handlers au remount.

| Proposition | A : cleanup socket.off dans chaque useEffect |

19. Battle hub incomplet

Routes 1vX existent ; hub nexpose que MultiPlayers + Coinflip stub. Copy “MultiPlayers” / redirects legacy.

| Proposition | A : cartes hub 1vX + Coinflip disabled clair · B : retirer Coinflip jusqu’à implémentation |

20. Guards auth copiés partout

Chaque page : loading / !user / admin redirect.

| Proposition | A : <RequireAuth> / <RequirePlayer> · B : loader React Router |

21. CasePage — complexité

State machine respin/auto-sell/announce via refs : difficile à maintenir, mais globalement correcte.

| Proposition | A : extraire hook useCaseOpenFlow · B : machine XState · C : laisser tel quel + tests dintégration |

22. Admin UX

  • Inputs prix en cents bruts + Number
  • Pas d’édition packs crédits / ads (seulement osu packs)
  • Adjust player sans confirm
  • Pas de lien “voir le site joueur”

| Proposition | A : champs crédits + confirm adjust · B : admin shop packs crédits |

23. Tests absents

Aucun test automatisé visible sur la logique critique (odds, cents, auto-sell, vault).

| Proposition | A : Vitest unitaire cents / wear / autoSell / duel weights · B : smoke API Playwright |

24. Observabilité

console.error local ; pas de métriques / tracing.

| Proposition | A : structured logs (pino) + request id · B : health DB ready |


P4 — Produit / design (nice to have)

# Sujet Proposition
25 Prestige sans confirm Dialog “tu perds inventaire + keys”
26 Catalog conservé au prestige Documenter (déjà le cas) ou option reset
27 Favoris bettables Clarifier UI ou bloquer en battle
28 Feed montre parfois FT Afficher valeur dinstance
29 Lazy routes / code-split React.lazy admin vs player
30 SQLite scale Postgres si charge / multi-instance
31 Achievements / shop ads hardcodés Config admin
32 Animation CaseReel perf Lazy images ; réduire slots si animReduction

Vérification logique (résumé métier)

Système Verdict
Drop case Serveur fait foi ; luck = catalog chapters + Fortune
Wear → prix Correct (FT = ref) ; Polish/Quality biaisent vers le haut
Auto-sell instance < seuil ; Yield après coup ; pas de bug “35T vendu sous 15T” si prestige max + vrai 35T instance
Keys Progression documentée ; keyOpenReduction non branché
Vault Timer partagé ; risque double settle
Jackpot Poids valeur OK
Duel Poids multi-items KO
Prestige joueur Wipe bal/inv/keys ; keep skills/Pr/catalog
Server prestige Wipe économie globale ; keep account/achievements/stats

Roadmap proposée (ordre dexécution)

Semaine 1 (P0)
  ├─ Fix duel toCentsBigInt + test
  ├─ Gate mock payments en prod
  ├─ Retirer reviveMoney Number(bigint)
  ├─ Allowlist uploads (no SVG)
  └─ Plan migration Docker (stop accept-data-loss au boot)

Semaine 2 (P1)
  ├─ BigInt-safe client (ItemTile, sorts, prestige shortfall, admin inputs)
  ├─ Balance updates atomiques + vault settle idempotent
  └─ Brancher ou supprimer prestige fields morts

Semaine 3 (P2P3)
  ├─ Rate limit + CORS prod + session store
  ├─ Refactor battle common + socket cleanup
  ├─ Hub 1vX + tests unitaires cents/odds
  └─ Confirms UX (prestige, admin adjust)

Alternatives darchitecture (si le projet grossit)

Option Quand Coût
Rester mono SQLite LAN / petits effectifs Faible — documenter single-node
Postgres + Redis (sessions, presence, timers) Multi-instances / uptime Moyen
Queue économie (BullMQ) Anti race balance/vault Moyen
Séparer worker (spins, vault ticks) Charge Socket.IO Élevé
Stripe live Monétisation réelle Moyen + conformité

Hors scope de cette analyse

  • Audit pentest complet / dépendances CVE détaillées
  • Refonte UI/UX visuelle
  • Implémentation Coinflip
  • Contenu (balancing drops / prix items)

Document généré pour pilotage : aucune modification code associée. Prioriser P0 avant tout déploiement Docker “réel”.