# امنیت

## Secretها

- همه‌ی Secretها از محیط خوانده می‌شوند (`.env` با `chmod 600`، یا متغیرهای محیطی / Secret Manager). `.env` در `.gitignore` است؛ فقط `.env.example` (بدون مقدار) در مخزن قرار دارد.
- توکن ربات‌ها در جدول `bots` با AES-256-GCM رمز می‌شوند و هیچ‌وقت در URL لاگ‌شده، خط فرمان یا خروجی فرمان‌ها ظاهر نمی‌شوند (`bot:add` توکن را از محیط می‌خواند، نه از آرگومان).
- رمز دیتابیس هنگام پشتیبان‌گیری از طریق `MYSQL_PWD` به پردازه‌ی فرزند داده می‌شود.
- لاگر مقدار هر کلیدی با نام `token`, `secret`, `password`, `api_key`, `authorization`, `card`, `iban`, `national`, `destination`, `phone`, `signature` را `***` می‌کند و الگوی توکن ربات را از متن پیام‌ها حذف می‌کند.

## داده‌ی حساس

| داده | نگهداری | نمایش |
|---|---|---|
| شماره کارت / شبا | رمزشده + HMAC برای یکتایی | `603799******1234` |
| مقصد برداشت | رمزشده | Mask؛ کامل فقط برای `withdrawals.approve` با ثبت در Audit |
| نام، کد ملی، موبایل (KYC) | رمزشده + HMAC کد ملی | فقط برای `kyc.view`، با ثبت در Audit |
| توکن Admin API | فقط HMAC | یک‌بار هنگام صدور |
| State گفتگو (Redis) | داده‌ی حساسِ میانِ مراحل رمزشده | — |

## تهدیدها و کنترل‌ها

| تهدید | کنترل |
|---|---|
| **SQL Injection** | فقط Prepared Statement واقعی (Emulation خاموش)؛ SQL فقط در Repositoryها؛ نام ستون‌های پویا از فهرست سفید (`UserRepository::increment`, `ExportRepository::ENTITIES`, فیلترهای `search`) |
| **Authorization Bypass** | هر متدِ `App\Admin\*Service` با `Authorizer::authorize()` شروع می‌شود؛ `callback_data` و Admin API هر دو از همین سرویس‌ها می‌گذرند. داده‌ی کاربر همیشه با مالکیت بررسی می‌شود (`forUser`, `ownedBy`, `cancelByUser`). مدیرِ مسدودشده فوراً دسترسی‌اش را از دست می‌دهد. فقط Super Admin می‌تواند نقش `super_admin` بدهد. |
| **Callback Forgery** | توکن تصادفی ۳۲ نویسه‌ای در آدرس Callback؛ تطبیق Authority / paymentUid با مقدار ثبت‌شده؛ امضای HMAC-SHA512 برای IPN؛ و در نهایت Verify مستقیم از درگاه با مبلغِ دیتابیس |
| **Replay Attack / Webhook Replay** | `update_id` یکتا (Redis `SET NX` + ایندکس یکتای MySQL)؛ همه‌ی عملیات حساس Idempotent |
| **Duplicate Payment** | قفل ردیف پرداخت + گذار `pending→paid` + کلید Ledger `payment:{id}` + `UNIQUE(tx_hash)` + `UNIQUE(gateway, authority)` |
| **Double Withdrawal** | خروج پول در لحظه‌ی ثبت درخواست، زیر قفل ردیف کیف پول؛ `UNIQUE(idempotency_key)`؛ Refund با کلید یکتا |
| **Race Condition** | `SELECT … FOR UPDATE`، قفل چند کیف پول به ترتیب ثابت، `UPDATE … WHERE status = ?`، `CHECK`های دیتابیس، Retry خودکار Deadlock |
| **Brute Force** | Admin API: شمارش تلاش ناموفق به ازای IP؛ ارسال TX Hash: ۶ بار در ۱۰ دقیقه؛ توکن‌ها ≥ ۱۴۰ بیت آنتروپی |
| **Spam / Flood** | `AbuseGuard`: ۴۰ Update در دقیقه و ۸ در ۳ ثانیه برای هر کاربر؛ بالاتر از دو برابر ← قفل موقت ۲ دقیقه‌ای. محدودیت تعداد پرداخت باز، تیکت باز، لینک فعال، حساب بانکی |
| **Secret Leakage** | بخش‌های «Secretها» و «داده‌ی حساس»؛ خطاها به کاربر فقط با کد پیگیری؛ `/health` بدون توکن جزئیات نمی‌دهد |
| **HTML Injection در پیام‌ها** | همه‌ی داده‌ی کاربر قبل از قرارگرفتن در پیام HTML با `Str::e()` Escape می‌شود؛ داده‌ی رویدادها یک‌جا در `NotificationService` |
| **CSV / Formula Injection** | مقادیر متنیِ شروع‌شونده با `= + - @` در خروجی‌ها با `'` خنثی می‌شوند |
| **جعل IP** | برنامه فقط `REMOTE_ADDR` را می‌خواند؛ اگر پشت Proxy هستید Real-IP را در Nginx تنظیم کنید، نه در PHP |
| **سوءاستفاده از واریز** | واریز درگاه قابل برداشت نیست؛ وضعیت «قابل برداشت» در انتقال بین کاربران همراه پول منتقل می‌شود |
| **تقلب در عضوگیری** | هر شخص یک‌بار در هر کمپین؛ ناشر/مالک از لینک خودش شمرده نمی‌شود؛ دوره‌ی نگهداری قبل از تسویه؛ `FraudDetector` (خروج سریع، Burst، خروج تکراری) با امتیاز ریسک و تعلیق خودکار لینک |

## Anti-Abuse

| سازوکار | کجا |
|---|---|
| Rate Limit کاربر | `Security\AbuseGuard` + `config/telegram.php` |
| قفل موقت | کلید Redis `abuse:lock:{bot}:{user}` |
| مسدودسازی کاربر | `users.status = blocked` (پنل ← کاربر ← مسدود کردن) |
| IP Limit در وب | `public/index.php` + `limit_req` در Nginx + `ADMIN_API_ALLOWED_IPS` |
| رفتار مشکوک | `risk_events` + پنل ← 🚨 رفتار مشکوک |
| هشدار مدیر | رویداد `admin_alert` ← چت `TELEGRAM_ADMIN_CHAT_ID` |

## Audit

`audit_logs` (فقط INSERT، بدون پاکسازی خودکار): مدیر، عمل، هدف، مقدار قبل و بعد، زمان، IP. هر تغییر دستی موجودی علاوه بر Audit یک ردیف `admin_adjustment` در Ledger دارد.

## چک‌لیست سرور

- [ ] `.env` با `chmod 600` و مالک `gostardeh`؛ `storage/backups` با `700`
- [ ] MySQL و Redis فقط روی `127.0.0.1`؛ Redis با `requirepass`
- [ ] فایروال: فقط ۲۲ (محدود به IP شما)، ۸۰، ۴۴۳
- [ ] `APP_DEBUG=false`
- [ ] `HEALTH_TOKEN` و (در صورت استفاده) `ADMIN_API_ALLOWED_IPS` تنظیم شده
- [ ] پشتیبان خارج از سرور و آزمون بازیابی
- [ ] `SUPER_ADMIN_IDS` فقط شامل افراد لازم؛ بقیه‌ی مدیران با نقش محدود
- [ ] کیف پول خزانه‌ی TRON/TON جدا از دارایی اصلی؛ کلید خصوصی آن **هرگز** روی این سرور نیست (سیستم فقط آدرس عمومی را می‌خواهد)
