# EL3AB Backend Architecture

**Derived from:** Supabase Master Audit (2026-06-03)
**Stack:** PHP 8.3 + Supabase REST API + Supabase Realtime

---

## Domain Model

```
┌─────────────────────────────────────────────────────────────────┐
│                        EL3AB PLATFORM                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────┐     ┌──────────────┐     ┌─────────────────┐     │
│  │   Auth   │────▶│   Profiles   │◀────│  Platform Roles │     │
│  │ (GoTrue) │     │  (48+ cols)  │     │  (RBAC system)  │     │
│  └──────────┘     └──────┬───────┘     └─────────────────┘     │
│                          │                                       │
│         ┌────────────────┼────────────────────┐                 │
│         │                │                    │                  │
│         ▼                ▼                    ▼                  │
│  ┌─────────────┐  ┌────────────┐   ┌──────────────────┐       │
│  │   GAMING    │  │   SOCIAL   │   │  ORGANIZATIONS   │       │
│  │             │  │            │   │                   │       │
│  │ • Chess     │  │ • Friends  │   │ • EL3AB Orgs     │       │
│  │ • Backgammon│  │ • Chat     │   │ • Swiss Orgs     │       │
│  │ • Domino    │  │ • Feed     │   │ • Members        │       │
│  │ • Ludo      │  │ • Notifs   │   │ • Rosters        │       │
│  │             │  │            │   │ • Treasury       │       │
│  └──────┬──────┘  └────────────┘   │ • Challenges     │       │
│         │                           └────────┬─────────┘       │
│         ▼                                    │                  │
│  ┌─────────────┐                            ▼                  │
│  │ COMPETITIVE │           ┌──────────────────────────┐        │
│  │             │           │     TOURNAMENTS          │        │
│  │ • Ratings   │           │                          │        │
│  │ • Leaderbd  │           │ • EL3AB (bracket/swiss)  │        │
│  │ • Matchmake │           │ • Swiss OTB (FIDE)       │        │
│  │ • Puzzles   │           │ • Registrations          │        │
│  └─────────────┘           │ • Brackets               │        │
│                            └──────────────────────────┘        │
│         ┌─────────────────────────────────────┐                 │
│         │            ECONOMY                   │                │
│         │                                      │                │
│         │ • Coins / Gems                       │                │
│         │ • Cosmetics (shop)                   │                │
│         │ • Achievements / XP                  │                │
│         │ • Daily Rewards                      │                │
│         │ • Org Treasury                       │                │
│         └─────────────────────────────────────┘                 │
│                                                                  │
│  ┌──────────────┐  ┌─────────────┐  ┌──────────────────┐      │
│  │   SPONSORS   │  │  CHARITIES  │  │  ADVERTISING     │      │
│  │              │  │             │  │  (campaigns/slots)│      │
│  └──────────────┘  └─────────────┘  └──────────────────┘      │
│                                                                  │
│  ┌──────────────────────────────────────────────────────┐      │
│  │                  ADMINISTRATION                       │      │
│  │  • Admin Panel Users • Audit Logs • Feature Flags    │      │
│  │  • System Config • Cheat Detection • Moderation      │      │
│  └──────────────────────────────────────────────────────┘      │
└─────────────────────────────────────────────────────────────────┘
```

---

## Authentication & Authorization

### Auth Flow
1. User signs up/logs in via Supabase GoTrue REST API
2. `on_auth_user_created` trigger creates profile in `profiles` table
3. JWT tokens (access + refresh) used for all API calls
4. Platform roles checked via `platform_roles` table + RLS policies

### Role Hierarchy
```
superadmin
  └── platform_admin
        └── org_owner
              └── org_admin
                    └── tournament_director
                          └── arbiter
                                └── content_manager
                                      └── match_moderator
                                            └── sponsor_admin
                                                  └── player
                                                        └── spectator
```

### Authorization Patterns
- **Public data:** Direct Supabase anon key queries (profiles, matches, leaderboards)
- **Own data:** Anon key + user JWT (notifications, economy, queue)
- **Org data:** Uses `user_has_role_in_org()` + `get_user_org_ids()` RLS helpers
- **Admin data:** Requires platform_roles check in RLS
- **Service operations:** Backend uses service_role key (org management, tournaments)

---

## API Architecture

### API Pattern
```
Client (Browser/JS)
    │
    ▼
/api/*.php (PHP proxy layer)
    │
    ├── Uses Supabase Anon Key (for user-context operations)
    │   └── Passes user JWT in Authorization header
    │
    └── Uses Supabase Service Key (for privileged operations)
        └── Rating updates, matchmaking, admin operations
```

### Key API Modules

| Module | Endpoint | Operations |
|--------|----------|------------|
| Auth | /api/auth.php | signup, login, logout, refresh, profile-create |
| Profile | /api/profile.php | get, update, upload-avatar |
| Game | /api/game.php | start, move, resign, draw, complete |
| Matchmaking | /api/matchmaking.php | queue, dequeue, find-match |
| Friends | /api/friends.php | request, accept, remove, block, list |
| Notifications | /api/notifications.php | list, mark-read, count-unread |
| Leaderboard | /api/leaderboard.php | get-by-game, get-by-time-control |
| Shop | /api/shop.php | list-items, purchase, equip |
| Achievements | /api/achievements.php | list, check-progress |
| Tournaments | /api/tournaments.php | list, register, cancel, brackets |
| Puzzles | /api/puzzles.php | random, by-rating, submit-solution |
| Ratings | /api/ratings.php | calculate, update, history |
| Daily Reward | /api/daily-reward.php | claim |
| Bots | /api/bots.php | list, play (proxy to Stockfish API) |
| Multiplayer | /api/multiplayer.php | create-room, join-room (domino/ludo) |
| Orgs | /api/orgs.php | list, join, leave, details |

---

## Data Flow: Game Lifecycle

### Chess vs Bot
```
1. Player selects bot + time control
2. POST /api/game.php (action=start, bot_id, time_control)
   → INSERT matches (status=in_progress, white_player_id, bot_id)
   → Return match_id
3. Player makes move (chess.js validates client-side)
4. POST /api/game.php (action=move, match_id, move)
   → UPDATE matches (moves jsonb, current_fen, move_count)
5. JS calls Stockfish API for bot response
6. POST /api/game.php (action=move, match_id, bot_move)
   → Same update
7. On game end:
   → UPDATE matches (status=completed, result)
   → Calculate Elo change
   → UPDATE profiles (rating, stats)
   → INSERT rating_history
   → INSERT economy_transactions (reward)
   → Check achievements
```

### Chess vs Human (Realtime)
```
1. Player joins matchmaking queue
2. POST /api/matchmaking.php (action=queue)
   → INSERT matchmaking_queue
3. Client subscribes to matchmaking_queue changes via Realtime
4. Backend/client finds match (rating range overlap)
   → UPDATE matchmaking_queue (status=matched, match_id)
   → INSERT matches
5. Both clients subscribe to matches row via Realtime
6. Moves: POST /api/game.php → UPDATE matches → Realtime broadcast
7. End: same as bot flow + both players' ratings updated
```

### Domino/Ludo (Realtime)
```
1. Create/join room: INSERT domino_matches/ludo_matches
2. Subscribe to row via Realtime
3. Moves: UPDATE game row → all players receive via Realtime
4. Full game state stored in JSONB columns (hands, board, positions)
```

---

## Rating System

### Elo Ratings
- Stored per player per game in `player_game_ratings`
- Legacy: `profiles.elo_bullet/blitz/rapid/classical` (chess only)
- New: `player_game_ratings` table (game_key + player_id)
- History tracked in `rating_history` per match
- Leaderboards cached in `leaderboards` table

### Calculation (server-side)
```
K-factor based on games played:
  < 30 games: K=40
  < 100 games: K=20
  else: K=10

Expected score: 1 / (1 + 10^((opponent_rating - player_rating) / 400))
New rating: old_rating + K * (actual_score - expected_score)
```

---

## Economy System

### Currencies
- **Coins** — earned through gameplay, daily rewards, achievements
- **Gems** — premium currency (future IAP)

### Earning Sources
- Match win: coins based on time control
- Daily reward: coins + streak bonus
- Achievement unlock: coins + gems
- Tournament prize: coins + gems
- Level up: coins + gems per xp_levels table

### Spending
- Cosmetics purchase (coins or gems)
- Tournament entry fees
- Org treasury donations (future)

---

## Realtime Architecture

### Channels Used
1. **Match Channel:** `matches:id=eq.{match_id}` — game state updates
2. **Queue Channel:** `matchmaking_queue:player_id=eq.{uid}` — match found
3. **Notifications:** `notifications:user_id=eq.{uid}` — new notifications
4. **Domino/Ludo:** `domino_matches:id=eq.{id}` / `ludo_matches:id=eq.{id}`
5. **Presence:** Supabase Presence for online status
6. **Tournament:** `tournament_brackets:tournament_id=eq.{id}` — bracket updates

### Client Implementation
```javascript
// Supabase JS client connects via WebSocket
const channel = supabase.channel('match-{id}')
  .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'matches', filter: `id=eq.${matchId}` }, handleUpdate)
  .subscribe()
```

---

## Service Dependencies

| Service | URL | Purpose |
|---------|-----|---------|
| Supabase Kong | https://safe-supabase-kong.caprover.al-arcade.com | API gateway |
| Supabase REST (PostgREST) | via Kong /rest/v1/ | Database CRUD |
| Supabase Auth (GoTrue) | via Kong /auth/v1/ | Authentication |
| Supabase Realtime | via Kong /realtime/v1/ | WebSocket |
| Supabase Storage | via Kong /storage/v1/ | File uploads |
| Stockfish API | https://stockfishapi.caprover.al-arcade.com | Chess bot moves |

---

## Security Considerations

1. **Service key** must never be exposed to client — only used server-side in PHP
2. **Anon key** is safe for client-side (RLS protects data)
3. **JWT validation** — PHP should validate token expiry before proxying
4. **Rate limiting** — not built into Supabase, needs application-level implementation
5. **Cheat detection** — `cheat_score`, `engine_correlation`, `avg_centipawn_loss` tracked per match
6. **Ban system** — `is_banned`, `ban_reason`, `ban_expires_at` on profiles
