# SpinWin Africa — Web / API (Agent Guide)

Backend Laravel du projet **SpinWin Africa**.  
Cadrage : `../spinwin-africa-docs/` — contrat `docs/api.md`, schéma MySQL `docs/architecture.md`.

Base : template **laravel-backend** (`/api`, Sanctum + `X-API-KEY` + Laratrust) **coexistant** avec l'API produit **`/v1`** (JWT Bearer, Auth OTP/PIN).

## Setup

```bash
# Depuis spinwin-africa-web/
composer install --ignore-platform-reqs   # si PHP 8.4 local
cp .env.example .env
php artisan key:generate
# Local: SQLite (défaut dans .env.example). Prod/staging: MySQL 8.
touch database/database.sqlite
php artisan migrate
pnpm install
pnpm run build   # assets Vite si besoin
php artisan serve
```

## Qualité

```bash
vendor/bin/pint
php artisan test   # Pest (sqlite :memory: en testing)
```

## Architecture actuelle

### Starter (`/api`)
- Routes : `routes/api/*.php`
- Auth template : Sanctum + `X-API-KEY` + Laratrust
- Réponses : trait `ApiResponse` (legacy)
- **Ne pas traiter comme le contrat mobile SpinWin**

### Produit (`/v1`)
- Routes : `routes/v1/*.php`, middleware group `v1` (pas de `CheckApiKey`)
- Auth : Bearer JWT (`auth:jwt`), refresh tokens en table `refresh_tokens` (rotation)
- Wallet : `GET/POST /v1/wallets/me*` ; ledger interne `WalletService::credit|debit` (idempotency + version)
- Game : `POST /v1/spins` mode `free` + `paid` (flag `SPINWIN_PAID_MODE_ENABLED`) ; cooldown 6h paid ; `GET /v1/spins/{id}/verify` après révélation seed
- Erreurs : `{ error: { code, message, details } }` via `ApiJsonResponse` / `Handler`
- Services : `app/Services/Auth/*`, `app/Services/Wallet/*`, `app/Services/Game/*`, `app/Services/Loyalty/*`, SMS `app/Services/Sms/*`
- Modèle `users` aligné `architecture.md` (UUID, `phone_number`, `pin_hash`, …)
- À l'inscription (`verify-otp`) : création atomique user + wallet + wallet_limits + kyc_records
- KYC N2 : `GET/POST /v1/kyc/*` ; auto-validate sandbox (`SPINWIN_KYC_AUTO_VALIDATE`) ; gate `KYC_REQUIRED` sur spins paid

## Cible produit (docs)

- Préfixe **`/v1/`**, Bearer **JWT**, erreurs `{ error: { code, message, details } }`
- Services : Auth (OTP) ✅ ; Wallet API ✅ ; Game free ✅ ; Game paid ✅ (flag) ; Payments **simulation** ✅ ; Loyalty ✅ ; KYC N2 ✅ ; Notifications, Admin RBAC à venir
- Écritures financières : `Idempotency-Key` + transactions atomiques (ledger interne)
- Admin : même repo, routes `/admin` (Inertia Vue) — session guard `admin` + table `admin_users`
- Mode payant gated (ADR-0003) ; KYC niveau 2

## Admin back-office (`/admin`)

- Auth session séparée des joueurs JWT (`guard: admin`, modèle `AdminUser`)
- RBAC : **`spatie/laravel-permission`** (guard `admin`, tables préfixées `spatie_*` pour cohabiter avec Laratrust legacy `/api`)
- Rôles produit : `super_admin`, `support`, `finance`, `game_manager` (`AdminRoleSeeder`)
- Pages Inertia : `resources/js/pages/Admin/*` (Dashboard, Users)
- Seed local : `SPINWIN_ADMIN_EMAIL` / `SPINWIN_ADMIN_PASSWORD` via `AdminUserSeeder`
- API JSON `/v1/admin/*` : pas encore branchée (UI session d’abord)
- Actions sensibles journalisées dans `audit_logs`

## Agent rules

- MySQL 8 uniquement (pas Postgres)
- `pnpm` pour le JS — pas npm/yarn
- Aligner le nouveau code sur `api.md`, pas seulement sur le boilerplate Sanctum
- Maj `spinwin-africa-docs` si API / métier / architecture changent
