# امنیت

## ۱. احراز هویت

| موضوع | پیاده‌سازی |
|---|---|
| هش گذرواژه | **Argon2id** (پارامترهای پیش‌فرض امن، بدون MD5/SHA خام) |
| نشست | کوکی `HttpOnly` + `SameSite=Lax` + `Secure` در تولید |
| ذخیره توکن نشست | فقط **هش SHA-256** در جدول `sessions`؛ توکن خام هرگز ذخیره نمی‌شود |
| انقضا | `expires_at` در پایگاه داده + انقضای کوکی |
| خروج | ابطال رکورد نشست در سرور، نه صرفاً حذف کوکی |

سرقت پایگاه داده به‌تنهایی اجازه‌ی جعل نشست نمی‌دهد، چون توکن خام موجود نیست.

## ۲. CSRF

الگوی **Double Submit Cookie**:
1. هنگام ورود، یک `csrfToken` تصادفی در کوکی غیر-HttpOnly `shahrnama_csrf` قرار می‌گیرد.
2. هر درخواست تغییردهنده (`POST/PATCH/PUT/DELETE`) باید همان مقدار را در سربرگ
   `X-CSRF-Token` بفرستد.
3. عدم تطابق ⇒ `403`.

کلاینت (`frontend/lib/api.ts`) این کار را خودکار انجام می‌دهد.

## ۳. XSS

- هیچ محتوای کاربر با `dangerouslySetInnerHTML` رندر نمی‌شود. تنها موارد استفاده،
  JSON-LD ساختاریافته‌ای است که خودمان از داده‌ی سریال‌شده می‌سازیم.
- React به‌صورت پیش‌فرض متن را escape می‌کند.
- CSP از طریق `@fastify/helmet` تنظیم شده و `object-src 'none'` و
  `frame-ancestors` محدود دارد.
- سرو فایل‌های آپلودی همیشه با `X-Content-Type-Options: nosniff` و
  `Content-Disposition: inline` انجام می‌شود.

## ۴. اعتبارسنجی ورودی

هر بدنه و پارامتر با **Zod** اعتبارسنجی می‌شود. فیلدهای حساس (`is_locked`,
`editable_until`, `verification_status`, `sla_breached_at`) اصلاً در اسکیمای ورودی
حضور ندارند، پس با «Mass Assignment» قابل تغییر نیستند.

## ۵. آپلود فایل

`backend/src/modules/media/service.ts`:

1. **Magic Number**: نوع فایل از بایت‌های ابتدایی تشخیص داده می‌شود، نه از پسوند
   یا سربرگ `Content-Type` که کاملاً قابل جعل است.
2. عدم تطابق نوع مجاز ⇒ `422`.
3. نام فایل بازتولید می‌شود (UUID)؛ نام کاربر هرگز وارد مسیر نمی‌شود.
4. `GET /api/media/file/*` مسیر نهایی را `path.resolve` کرده و بررسی می‌کند حتماً
   زیر پوشه‌ی ذخیره‌سازی باشد ⇒ جلوگیری از **Path Traversal**.
5. سقف حجم بدنه: ۲ مگابایت (`bodyLimit`).

## ۶. SSRF

هر جا سرور آدرس بیرونی می‌گیرد (منبع مجموعه‌داده، وب‌سایت سازمان)، آدرس فقط
**ذخیره و نمایش** داده می‌شود و سرور آن را واکشی نمی‌کند. تنها درخواست خروجی
سامانه، فراخوانی API پیام‌رسان‌ها با میزبان ثابت و از پیش تعیین‌شده است.
پیوندهای بیرونی در رابط کاربر با `rel="noopener noreferrer nofollow"` رندر می‌شوند.

## ۷. محدودسازی نرخ

| مسیر | سقف |
|---|---|
| کلی | ۳۰۰ درخواست در دقیقه |
| `POST /auth/login` | ۱۰ در ۵ دقیقه |
| `POST /auth/register` | ۵ در ۱۰ دقیقه |
| `POST /civic/reports` | ۱۲ در ساعت |
| `POST /me/comments` | ۲۰ در ساعت |

## ۸. CORS

فقط `localhost:*` و `*.e2b.app` (محیط پیش‌نمایش) مجازند. در تولید باید به دامنه‌ی
واقعی محدود شود.

## ۹. حسابرسی

`audit_logs` این کنش‌ها را ثبت می‌کند: ورود و خروج، تغییر نقش، تأیید/رد سازمان و
کسب‌وکار، انتشار و اصلاحیه‌ی خبر، **تلاش ناموفق برای ویرایش محتوای قفل‌شده**،
تغییر تنظیمات، تغییر کانال ارتباطی، گذارهای پرونده، نقض SLA.

هر رکورد شامل: کنش، بازیگر، نوع و شناسه‌ی موجودیت، مقدار قبل و بعد، IP و زمان.

## ۱۰. حریم خصوصی

- گزارش‌های ناشناس: `reporter_user_id` در لایه‌ی سرویس `null` می‌شود، پس حتی برای
  سازمان مسئول هم قابل بازیابی از API نیست.
- گزارش‌های خصوصی: مختصات جغرافیایی از پاسخ حذف می‌شود، پس روی نقشه قابل استنتاج نیست.
- مسیرهای پنل (`/account`, `/studio`, `/admin`, `/moderation`, `/org/*`, `/business/*`)
  در `robots.txt` از نمایه‌سازی خارج شده‌اند و متادیتای `robots: { index: false }` دارند.

## ۱۱. آنچه پیش از تولید باید انجام شود

- [ ] تنظیم `SESSION_SECRET` و `POSTGRES_PASSWORD` قوی از مدیر رمز
- [ ] فعال‌سازی HTTPS و `Secure` روی کوکی‌ها
- [ ] محدود کردن CORS به دامنه‌ی واقعی
- [ ] فعال‌سازی احراز هویت دومرحله‌ای برای نقش‌های `admin` و `super_admin`
- [ ] اجرای اسکن وابستگی (`npm audit`) در CI
- [ ] آزمون بازیابی نسخه پشتیبان (`datacenter/backups/scripts/restore.sh`)
