shop stipe
This commit is contained in:
+36
-47
@@ -1,6 +1,6 @@
|
||||
# CaseOrion — Analyse & améliorations
|
||||
|
||||
**Date :** 2026-07-25
|
||||
**Date :** 2026-07-25 · **MAJ :** 2026-07-26
|
||||
**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.
|
||||
|
||||
@@ -9,14 +9,13 @@
|
||||
## 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).
|
||||
Les risques les plus graves restants : **paiements mock en prod**, **`db push --accept-data-loss` au boot**, 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) |
|
||||
| Battle (jackpot only) | Un seul mode ; 1vX / coinflip / duel **retirés** |
|
||||
| Vault / prestige | Fonctionnel ; settle concurrent risqué |
|
||||
| Shop | Mock OK en dev ; dangereux si prod |
|
||||
| Docker | Marche en single-node ; pas scale-ready |
|
||||
@@ -26,18 +25,14 @@ Les risques les plus graves sont : **odds duel cassées**, **paiements mock en p
|
||||
## 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`.
|
||||
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` et `/battle/coinflip` redirigent vers `/battle`.
|
||||
|
||||
### 1. Paiements mock utilisables en production
|
||||
**Fichiers :** `server/src/payments.js`, `routes/shop.js`, `.env.prod.example`
|
||||
### 1. Paiements mock utilisables en production — **en cours (B Stripe)**
|
||||
**Fichiers :** `server/src/payments.js`, `routes/shop.js`, `index.js` (webhook raw body), `.env.prod.example`
|
||||
|
||||
`PAYMENTS_PROVIDER=mock` + `POST /api/shop/osu/confirm` crédite l’osu **sans paiement**.
|
||||
Stripe Checkout + webhook `checkout.session.completed` branchés. En prod Docker : `PAYMENTS_PROVIDER=stripe` + `STRIPE_*` keys + `STRIPE_WEBHOOK_SECRET` + URL publique HTTPS vers `/api/shop/osu/webhook`.
|
||||
|
||||
| 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 |
|
||||
Reste : désactiver mock en prod (A) si quelqu’un oublie `PAYMENTS_PROVIDER` ; bascule live keys quand le compte est vérifié.
|
||||
|
||||
---
|
||||
|
||||
@@ -46,11 +41,7 @@ Le mode **1vX Case** (rooms custom / `duel.js`) a été **retiré** (2026-07-25)
|
||||
|
||||
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 |
|
||||
| Proposition | A (recommandé) : Prisma Migrate (`migrate deploy`) ; push manuel hors boot · B : push **sans** `--accept-data-loss` + fail loud · C : job one-shot de migration séparé du `CMD` app |
|
||||
|
||||
---
|
||||
|
||||
@@ -126,25 +117,30 @@ Min 6 caractères seulement.
|
||||
|
||||
## P3 — Qualité code / refactor
|
||||
|
||||
### 16. Duplication jackpot ↔ duel
|
||||
Serialize, finish spin, auto-sell winner : quasi copy-paste.
|
||||
### ~~16. Duplication jackpot ↔ duel~~ — **obsolète**
|
||||
`duel.js` / 1vX / coinflip **retirés** ; un seul type de battle (`services/jackpot.js`). Plus de duplication cross-mode à factoriser.
|
||||
|
||||
| Proposition | A : module `services/battleCommon.js` · B : unifier modèle “room” (plus gros refactor) |
|
||||
| Ancienne prop. | A : `services/battleCommon.js` · B : unifier modèle “room” — **non pertinent** tant qu’il n’y a qu’un mode |
|
||||
|
||||
Si un 2ᵉ mode battle revient plus tard, reprendre **A** d’abord (helpers serialize / finish / auto-sell), **B** seulement si les rooms divergent vraiment.
|
||||
|
||||
### 17. `serializeInv` dupliqué
|
||||
`inventory.js` / `profile.js` (et variantes).
|
||||
|
||||
| Proposition | A : `serializeInventoryItem` partagé |
|
||||
| Proposition | **A (retenu)** : `serializeInventoryItem` partagé (module commun serveur) |
|
||||
|
||||
### 18. Client — listeners `socket.on('connect')` jamais retirés
|
||||
Layout, BattleHub, BattleRoom, Duel*, DropFeed → fuite de handlers au remount.
|
||||
**Fichiers :** `Layout.jsx`, `BattleHub.jsx`, `BattleRoomPage.jsx`, `DropFeed.jsx`
|
||||
(les pages Duel* n’existent plus)
|
||||
|
||||
| Proposition | A : cleanup `socket.off` dans chaque `useEffect` |
|
||||
Les `useEffect` font souvent `socket.off` des events métier, mais **pas** du handler `connect` → fuite au remount / Strict Mode.
|
||||
|
||||
### 19. Battle hub incomplet
|
||||
Routes 1vX existent ; hub n’expose que MultiPlayers + Coinflip stub. Copy “MultiPlayers” / redirects legacy.
|
||||
| Proposition | **A (retenu)** : nommer le handler `onConnect` et `socket.off('connect', onConnect)` dans chaque cleanup |
|
||||
|
||||
| Proposition | A : cartes hub 1vX + Coinflip disabled clair · B : retirer Coinflip jusqu’à implémentation |
|
||||
### ~~19. Battle hub incomplet~~ — **résolu / simplifié**
|
||||
Hub = **un seul** mode Battle (jackpot MultiPlayers). 1vX et Coinflip **n’existent plus** (redirects legacy vers `/battle`). Plus de cartes stub / copy multi-modes à aligner.
|
||||
|
||||
---
|
||||
|
||||
### 20. Guards auth copiés partout
|
||||
Chaque page : loading / !user / admin redirect.
|
||||
@@ -167,7 +163,7 @@ State machine respin/auto-sell/announce via refs : difficile à maintenir, mais
|
||||
### 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 |
|
||||
| Proposition | A : Vitest unitaire `cents` / `wear` / `autoSell` / jackpot weights · B : smoke API Playwright |
|
||||
|
||||
### 24. Observabilité
|
||||
`console.error` local ; pas de métriques / tracing.
|
||||
@@ -197,12 +193,12 @@ Aucun test automatisé visible sur la logique critique (odds, cents, auto-sell,
|
||||
|---------|---------|
|
||||
| **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é |
|
||||
| **Auto-sell** | `instance < seuil` ; Yield après coup ; respin + auto-sell : keepers (≥ seuil) conservés |
|
||||
| **Keys** | Progression documentée ; reset keys au prestige joueur, **totalOpens conservé** |
|
||||
| **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** |
|
||||
| **Battle / Jackpot** | Seul mode battle ; poids valeur OK |
|
||||
| **1vX / Duel / Coinflip** | **Retirés** |
|
||||
| **Prestige joueur** | Wipe bal/inv/keys ; keep skills/Pr/catalog/**opens-by-case** |
|
||||
| **Server prestige** | Wipe économie globale ; keep account/achievements/stats |
|
||||
|
||||
---
|
||||
@@ -210,22 +206,15 @@ Aucun test automatisé visible sur la logique critique (odds, cents, auto-sell,
|
||||
## Roadmap proposée (ordre d’exécution)
|
||||
|
||||
```
|
||||
Semaine 1 (P0)
|
||||
├─ Fix duel toCentsBigInt + test
|
||||
Semaine 1 (P0 restant)
|
||||
├─ 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 (P2–P3)
|
||||
Semaine 2 (P2–P3)
|
||||
├─ Rate limit + CORS prod + session store
|
||||
├─ Refactor battle common + socket cleanup
|
||||
├─ Hub 1vX + tests unitaires cents/odds
|
||||
├─ serializeInventoryItem partagé
|
||||
├─ socket.off('connect', onConnect) (Layout, Battle*, DropFeed)
|
||||
├─ Tests unitaires cents / wear / autoSell / jackpot
|
||||
└─ Confirms UX (prestige, admin adjust)
|
||||
```
|
||||
|
||||
@@ -247,9 +236,9 @@ Semaine 3 (P2–P3)
|
||||
|
||||
- Audit pentest complet / dépendances CVE détaillées
|
||||
- Refonte UI/UX visuelle
|
||||
- Implémentation Coinflip
|
||||
- Réintroduction Coinflip / 1vX (non prévu)
|
||||
- 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”.*
|
||||
*Document de pilotage. Prioriser P0 restant avant tout déploiement Docker “réel”.*
|
||||
|
||||
Reference in New Issue
Block a user