# Architecture

## Stack (Ultrahost shared)

- PHP 8.2 + Laravel 11
- MySQL 8
- Blade + vanilla JS (5s polling)
- Cron for rates + `schedule:run`
- No Redis/WebSocket (optional later on VPS)

## Domain modules

| Module | Tables | Services |
|--------|--------|----------|
| Ledger | `wallets`, `ledger_entries` | `LedgerService` |
| Rates | `rate_ticks`, `rate_ohlc` | `PriceProviderChain`, `RateService` |
| MAM | `mam_strategies`, `mam_followers`, `master_trades`, `allocations` | `MamAllocationService`, `TradePnlService` |
| Payments | `deposit_requests`, `withdrawal_requests` | `WithdrawalService` |
| KYC | `kyc_submissions`, `kyc_documents` | `KycService` |
| Marketing | `referral_codes`, `operator_companies` | — |

## Ledger rules

- Balances are **sum of ledger entries**, never updated in place
- `cash` vs `bonus` buckets; `BONUS_PROFIT_CONVERT` moves profit to cash
- Withdrawal hold: `WITHDRAWAL_HOLD` / `WITHDRAWAL_RELEASE`
- Leverage fixed at wallet open (`max_leverage` immutable)

## MAM allocation

```
follower_lot = floor(master_lot * (follower_equity / sum_equity), 0.01)
remainder → master or largest follower
```

## User-visible vs internal

- Trade history view regenerated on admin recalc; no "adjustment" rows for users
- `audit_logs` + `record_snapshots` for deletes/recalcs (admin/operator only)
