# Sprint 2 — نسيت كلمة السر (Forgot Password)

> اسبرينت مرتّب بالاعتماديات، يجمّع ملفات الخطط أدناه. **قابل للتنفيذ مباشرةً:** شدّ المساعد على هذا الملف ينفّذ الاسبرينت كله.

## ▶ تنفيذ الاسبرينت (في Cursor)
افتح هذا الملف وقل للمساعد:
```
نفّذ هذا الاسبرينت بالكامل (sprints/2.md): اقرأ كل ملف خطة في «النطاق» ونفّذه عبر docs/build/* ثم احفظ.
```

> 📋 **لوحة الكانبان (`/kanban`):** سيب `/kanban` مفتوح — كل خطوة تظهر **لايف**. لو التاسكات مش ظاهرة، شغّل `php artisan board:sync` مرة.

**عقد التنفيذ للمساعد:**
1. **بوابة الاسبرينت (مرة واحدة):** اعرض «فكّر-الأول» + أي **design pattern** مقترح، واطلب موافقة المطوّر (نعم/لا).
   - بعد الموافقة **وقبل أول خطة**: `php artisan board:set --sprint=2 --status=in_progress`.
2. لكل ملف خطة في «النطاق» — **علّم كل حالة لحظتها، مش دفعة في الآخر:**
   - **قبل ما تبدأ الخطة:** `php artisan board:set --sprint=2 --plan=<plan-path> --status=in_progress` (الكارت يروح «قيد التنفيذ» لايف).
   - **API** → [`../build/build-api.md`](../../build/build-api.md) — مقاد بالخطة بالظبط.
   - ثم [`build-tests`](../../build/build-tests.md).
   - **بعد ما الخطة تعدّي:** `php artisan board:set --sprint=2 --plan=<plan-path> --status=done`.
3. **بوابة الإنجاز (DoD)** [`verify.md`](../../build/verify.md) §B.
4. [`build-postman`](../../build/build-postman-collection.md) — أضف الـ requests (قسم `Auth` → فولدر `forgot-password`).
5. **commit checkpoint** + سجّل الـ DoD بالأسفل.

> **لا تتجاوز ما هو مذكور في الخطط.**

## النطاق (ملفات الخطط في هذا الاسبرينت)
- forgot-password (3 خطوات مترابطة): `docs/project/api/user/forgot-password/request-code.md` · `docs/project/api/user/forgot-password/verify-code.md` · `docs/project/api/user/forgot-password/reset-password.md`

## الاعتماديات
- يعتمد على: — (الاسكيما reuse بالكامل: `users` + `otps` — feature `account_security`؛ مفيش أعمدة جديدة).

## فكّر-الأول (think-first)
- **الكيانات:** `users` (تحديث `password`) + `otps` (reuse — `type = OtpType::FORGET_PASSWORD` موجود في الـ base + `verification_code`/`status`/`tries`). **مفيش تغيير اسكيما.**
- **لبنات Laravel:**
  - **Sanctum abilities (temp token):** الخطوة 1 تُصدر `createToken('forget-password', ['forget-password'], now()->addMinutes(15))`؛ الخطوتان 2/3 محميّتان بـ `auth:sanctum` + **`ability:forget-password`** (سجّل الـ alias في `bootstrap/app.php` — [`build-auth-audience.md`](../../build/build-auth-audience.md)). الخطوة 3 **تبطّل التوكن** بعد النجاح.
  - **`OtpService`** (`sendOtp`/`verifyOtp`/`failActiveOtps`) + `OtpType::FORGET_PASSWORD`.
  - **Notifications** (`UserNotification` عبر `SendNotificationJob`): «محاولة تغيير كلمة السر» (خطوة 1) + «تم تغيير كلمة السر» (خطوة 3) — [`build-side-effects.md`](../../build/build-side-effects.md). **Events:** `PasswordResetRequested`, `PasswordChanged`. تحديث كلمة السر داخل `DB::transaction`.
- **الفلو متعدّد الخطوات (قاعدة إلزامية):** `request-code → verify-code → reset-password` — endpoint لكل خطوة، وما يعرفش يقفز:
  - خطوة 2 من غير temp token → 401 · خطوة 3 من غير ما OTP يبقى `FINISHED` → 409.
- **الافتراضيات:** `country_code` غير مُرسَل → `966` (في `prepareForValidation`).
- **الرسائل:** نصوص النجاح/الإشعارات بالظبط في `lang/{ar,en}/api/auth.php` (مش عامة).

## design pattern (فقط لو يستحق)
- **مش محتاج pattern جديد** — إعادة استخدام `OtpService` + Sanctum abilities (سابقة `activation` token) + Notifications/Events بتوع الـ base.

## نتيجة الإنجاز (DoD) — تُملأ بعد التنفيذ
```
migrate:fresh --seed:  ✅
pint:                  ✅
dump-autoload -o:      ✅
schema:check:          ⚠️ (pre-existing: empty cms feature + polluted DB tables)
php artisan test:      ✅  9/9 ForgotPasswordTest
smoke (ar+en):         ✅  (ar via Accept-Language + en default in tests)
commit:                96cba94
```
