---
name: api-security-cost-protection
description: حماية مسارات التصيير والصوت من الإساءة واستنزاف التكلفة — حدود معدل وحدود موارد وتحقق من URLs خارجية
version: 1.0.0
---

# API Security & Cost Protection

حين يعمل الوكيل على `/api/render` أو `/api/tts` أو أي مدخل يقبل URLs/نصوصاً من المستخدم، اتبع هذا الـ skill. نطاق المراجعة موثق أدناه — لا تدّعِ "الأمان الكامل" أبداً.

## الوضع الحالي (نقاط الضعف المعروفة — لا تخفها)

- الحد في الذاكرة (`src/lib/rate-limit.ts`: TTS ‏20/5min، render ‏5/hour لكل IP) **لا يعمل عبر نسخ serverless متعددة** — مهاجم بأ IPs متعددة أو نسخ متعددة يتجاوزه. النقل إلى Upstash Redis مخطط (المرحلة 3) ولم يُنفذ.
- `/api/render` **بلا مصادقة**: أي زائر يحصل على 5 تصييرات/ساعة — ثغرة تكلفة مباشرة (sandbox دقائق لكل عملية).
- `BackgroundMedia.url` و`imageUrl` و`musicUrl` و`audioUrl` تقبل أي `https` — لا قائمة سماح ولا فحص SSRF من طرف الخادم اليوم.
- الأخطاء لا تسرب مفاتيح حالياً، لكن `executeApi` يرد 500 على كل شيء (يُخفي أخطاء العميل ويصعّب المراقبة).

## ملفات يجب فحصها أولاً

- `src/lib/rate-limit.ts` (`checkRateLimit`، `clientIp` من `x-forwarded-for`/`x-real-ip`، `rateLimitedResponse` مع `Retry-After`).
- `src/app/api/render/route.ts` (حد 5/ساعة، فحص `BLOB_READ_WRITE_TOKEN`، تحقق `AnyRenderRequest`→`ShortProps`/`CompositionProps`).
- `src/app/api/tts/route.ts` (حد 20/5min، `TtsRequest`، مسار الكاش قبل التوليد).
- `types/shorts.ts` (قيود: `hook ≤120`، `scene ≤280`، `scenes ≤12`، `captions ≤600`، `audio ≤60s`؛ `src/lib/tts.ts` `MAX_TTS_CHARS=1000`).
- `src/helpers/api-response.ts` (التوحيد الحالي ونقص تمييز 400/429/500).

## سير العمل

1. **قيّد قبل التكلفة**: أي فحص رخيص (Zod، طول، عدد مشاهد، حد معدل) يجب أن يعمل **قبل** إنشاء sandbox أو استدعاء TTS. انقل أي فحص مكلف إلى ما بعد البوابات.
2. **حدود الموارد الصريحة**: مشاهد ≤12، مدة ≤60s، نص TTS ≤1000 (Edge) / تقسيم 200 (Groq)، `captions ≤600`. أي رفع حد يتطلب تحليل تكلفة `$` وزمن في وصف التغيير.
3. **عناوين IP**: `clientIp` يثق بترويسات الوكيل — وثّق ذلك. عند النقل إلى Redis استخدم نفس الواجهة (`checkRateLimit`) ومفتاح `tts:<ip>` / `render:<ip>` مع انتهاء صلاحية = النافذة.
4. **URLs خارجية**: طبق سياسة `cinematic-media/SKILL.md` (https فقط، رفض الخاص/metadata/`file://`). أي جلب خادم جديد: مهلة صريحة + حد حجم + قائمة MIME + رفض إعادة التوجيه إلى خاص.
5. **المقاييس الآمنة**: سجّل العدد والمدة والتكلفة (`rendering-performance/SKILL.md`) دون نصوص المستخدم أو مفاتيح.

## المعايير

- لا تمثل حد الذاكرة كحل موزع — علّق صراحة أنه أحادي النسخة حتى النقل إلى Redis.
- `Retry-After` إلزامي مع كل 429. رسائل الحدود عربية ومفيدة دون كشف العتبات الداخلية بدقة زائدة.
- المهلات: sandbox/render بحد أقصى موثق؛ TTS ‏60s؛ أي مزود جديد بمهلة + إلغاء (`AbortController`).
- التزامن: حدّد عدد عمليات sandbox المتوازية لكل نسخة؛ ادمج مشاهد المشروع في جلسة واحدة بدل `stop()` بين المشاهد حيث أمكن (بند المرحلة 3).

## الاختبار (`bun test`)

- غطِّ: تجاوز الحد (مسموح → مرفوض + `Retry-After`)، إعادة ضبط النافذة، حدود الموارد (13 مشهداً/280+ حرفاً/نص 1001 حرف تُرفض)، URL داخلي مرفوض، خطأ لا يسرب مفتاحاً.
- اختبارات إساءة: دفق طلبات متزامنة على نفس المفتاح، `x-forwarded-for` مُنتحل، إعادة توجيه URL إلى خاص.
- لا تدّعِ اختباراً دون تشغيل `bun test`.

## معايير القبول

- كل مسار مكلف خلف: تحقق مدخل + حد معدل + حد موارد + مهلة.
- لا وصول من URLs يتحكم بها المستخدم إلى خدمات داخلية (مُختبر).
- تغييرات الأمان تشمل اختبارات انحدار وتوثيق نطاق/مخاطر متبقية في وصف التغيير.

## التوثيق المطلوب

- سجل في وصف التغيير: ما رُوجِع (`/api/render`، `/api/tts`)، ما لم يُراجَع، والمخاطر المتبقية (بلا مصادقة، حد ذاكرة أحادي، لا قائمة سماح URLs بعد — حتى تُعالج).

## القيود والممنوعات

- ممنوع الادعاء بأن التطبيق "آمن" بعد هذه الفحوص — وثّق النطاق والمتبقي.
- ممنوع اعتماد Redis لمجرد وروده في خطة — اعتمده فقط لحد موزع/حالة مشتركة مع توثيق التكلفة والفشل والانتهاء والتوافق مع Vercel.
- ممنوع تسجيل نصوص المستخدم أو المفاتيح أو URLs موقعة في السجلات/المراقبة.
