# CONTEXT — read this FIRST (every session), then proceed

> **Purpose:** the one file an agent reads to get oriented — **so it does NOT re-scan the whole repo**
> each session (that burns time + tokens). It holds: the **map** (where things live), the **state**
> (what's been built + decisions), and the **patterns to mirror** (exact reference files to copy).
>
> **Rule for the agent:** read this file + the task's plan/sprint file, then **act**. Open a specific
> source file **only** when a pattern below points you to it. Do **not** explore the codebase broadly
> unless something you need is genuinely missing here — if so, add it here after you find it.
>
> **Keep it fresh:** at each sprint's Definition of Done, append one line to **§B** (what was built +
> any new reference pattern). This file is the project's memory.

---

## §A — Map (where everything lives)

| Layer | Path |
|---|---|
| Models | `app/Models/` (translatable → `+ {Model}Translation`) |
| Enums | `app/Enums/` (use `App\Traits\Enums\GeneralEnumTrait`; `const PATH` for labels) |
| Admin controllers | `app/Http/Controllers/Admin/` (extend `AdminBaseController`) |
| API controllers | `app/Http/Controllers/Api/V1/` — a **flow** = subfolder of focused controllers (`Auth/`) |
| Admin services | `app/Services/Admin/` · Domain/API services | `app/Services/<Area>/` |
| Admin requests | `app/Http/Requests/Admin/{Entity}/` · API requests | `app/Http/Requests/Api/{Module}/` (extend `BaseApiRequest`) |
| API resources | `app/Http/Resources/Api/V1/` (auth: `app/Http/Resources/Auth/`) |
| Response traits | `app/Traits/Response/` (`respondWithSuccess/Fail/Paginated`) |
| Upload traits | `app/Traits/Upload/` (Spatie media; model `FILES` const) |
| Admin views | `resources/views/admin/{module}/` (Blade = presentation only) |
| Routes | admin `routes/admin.php` · API `routes/api/v1/*.php` (auto-mounted — never edit `bootstrap/app.php`) |
| Lang | `lang/{ar,en}/` (`admin/*`, `api/*`, `validation.php`) — default `ar` |
| Hiring models | `Provider`, `JobPost` (+ translation), `JobCategory`, `Skill`, `CareerField`, `JobApplication`, `Interview`, `Education`, `Experience`, `Certificate`, `Plan`, `Subscription`, `CandidateRequest` |
| Schema (data) | `database/schema/*.json` (+ `features.json`) → `/schema-designer` |
| Migrations | `database/migrations/{domain}/` (additive only) · hiring: `database/migrations/hiring/` |
| Config | `config/sidebar_routes.php`, `config/auth.php` (`user` + `provider` guards) |
| Build playbooks | `docs/build/*` · Templates | `docs/project-init/*` · Plans | `docs/project/{api,cruds,sprints}/` |
| Kanban | `/kanban` (board `docs/project/board.json`; `php artisan board:sync` / `board:set`) |
| Postman | `docs/postman/daleel-hr.postman_collection.json` (skeleton — fills per sprint) |

Architecture (enforced): **thin controller → Form Request → Service → Resource/response trait**. Blade
presentation-only. Details: `CLAUDE.md` + `.claude/context/{project,domain,team}.md`.

---

## §B — State (what's built + decisions) — APPEND per sprint at DoD

**Base baseline (ships with the template):** admin auth (session `auth:admin` + RBAC), user management,
API auth (phone + OTP, Sanctum), complaints, contact messages, notifications (FCM + DB), settings,
geography (country/region/city/district, translatable), pages/faqs/sliders/seo/socials/intro (translatable),
media (Spatie), OTP (`OtpService` + `OtpType`), landing site, schema-designer, kanban.

**Project sprints (fill as you go):**
- `✅ START 0–7` — هوية + تحليل + لاندنج + schema `hiring` + طبقة DB + **كل الخطط** (API/CRUD/sprints 3–8 + Postman skeleton + kanban). **لا كود اسبرينت بعد.** راجع الخطط ثم نفّذ كل اسبرينت يدوياً.
- `✅ Sprint 1` — أمان الحساب (change phone/email) — خطط + تنفيذ base. تغيير كلمة المرور أُزيل لاحقًا.
- `✅ Sprint 2` — نسيت كلمة السر — أُلغي. الدخول برقم الجوال ورمز التحقق فقط.
- `✅ Sprint 3` — مصادقة user+provider + نفاذ stub · مسارات `/api/v1/user/*` و `/api/v1/provider/*` · مرجع: `Api/V1/User/Auth/*` + `ProviderAuthService` · تسجيل الأعمال يقبل `sector` و `company_size` في نفس `POST /provider/auth/register`
- `✅ Sprint 4` — ملف الباحث + وسائط · `Api/V1/User/Profile/*` + `UserProfileService` · `GET /api/v1/skills`
- `✅ Sprint 5` — وظائف + تقديمات · `JobPostBrowseService` / `ProviderJobPostService` / `JobApplicationService` · match = مهارات 60 + مدينة 25 + عنوان مستهدف 15 · الوظيفة تُحفظ فور الإضافة وتظهر من `starts_at` حتى `expires_at` · حالة التقديم في الرد تُحسب لكل مشاهد: `new` / `under_review` / `under_study` / `rejected` · تغيير جوال مقدم الخدمة `POST /api/v1/provider/auth/change-phone/*`
- `✅ Sprint 6` — مقابلات + مرشحون · `InterviewService` / `CandidateService` · بحث بدون national_id/nafath_raw
- `✅ Sprint 7` — باقات/اشتراكات بدون بوابة · `BillingService` · trial 30 يوم ثم `ends_at` حسب interval · 409 لو اشتراك نشط مكرر
- `✅ Sprint 8` — أدمن CRUDs (users موسّع + hiring/billing) · `DashboardHomeService` · `ReportService` · شكاوى/إشعارات API reuse
- `✅ بعد سبرنت 8` — `GET /api/v1/provider/notifications` بنفس شكل قائمة الباحث
- `✅ إشعارات kite + FCM` — شكل payload `title`/`message` ثنائي اللغة + `notification_type` + ids · `FirebaseV1Trait` + `devices` morph · sync جهاز عند verify-otp/register · `NotificationResource` يرجع `title`/`body`/`is_read`/`data`
- `✅ دخول بدون كلمة مرور` — الباحث ومقدم الخدمة يدخلان بـ `request-code` ثم `verify-otp`. لا إرسال ولا إرجاع لكلمة المرور. مسارات login / forgot-password / change-password أُزيلت.
- `✅ إشعارات الرئيسية وإلغاء اشتراك الأعمال` — `is_notify` في `PATCH /user/profile` و`PATCH /provider/auth/me` (الإشعار يُخزَّن، والـ push يتوقف عند `false`) · `GET /user/home` يرجع `interviews` · `POST /provider/subscriptions/{id}/cancel`
- `✅ الإيميل من تحديث الملف` — `email` في `PATCH /user/profile` و`PATCH /provider/auth/me`. دورة `change-email` أُزيلت. تغيير الجوال يبقى `verify-current → set-new → verify-new`.
- `✅ إصلاح داشبورد الأدمن` — جداول/شاشات/إحصائيات التوظيف والفوترة + إلغاء اشتراك + فلتر عنوان الوظيفة + ملف المشرف image
- `✅ الوظائف المستهدفة` — `GET /api/v1/user/target-jobs` قائمة وظائف متوافقة مع المدينة/المهارات/`job_title` · جدول `target_jobs` أُسقط · توافق العنوان من `users.job_title`
- `✅ تأكيد السيرة والمجالات` — `POST /api/v1/user/profile/cv-data` · `GET/PUT /api/v1/user/career-fields` · `POST /api/v1/user/cv/generate` (PDF) `|analyze|improvements/apply` · `GET /api/v1/user/cv` · التجربة تبقى `POST /api/v1/user/subscriptions`

**Key decisions (project-wide):**
- اسم المنتج: دليل مدينتي / Daleel Madinati — المصدر Figma فقط (لا brief).
- Model A: `users` + `providers` + Sanctum `auth:user` / `auth:provider`. نوع الحساب يُختار بعد الدخول: `GET/PATCH /api/v1/provider/auth/provider-types|provider-type`. القيم: `hr_staff|company_owner|recruitment_company|volunteer_hours|training_course|training_job|job_ad`. الباحث ومقدم الخدمة بلا كلمة مرور: الدخول `request-code` ثم `verify-otp`. عمود `password` يبقى nullable ومخفيًا ولا يُرسل ولا يُرجع.
- لا تصفّح كضيف؛ نفاذ stub (`national_id`/`nafath_id`/`nafath_raw`)؛ تطوع/تدريب = `job_posts.purpose`.
- باقتان (user/provider) سعرهما من الأدمن — seed 1200 هللة/سنة + 30 يوم تجربة؛ لا جداول بطاقة.
- جدول الوظائف اسمه `job_posts` (Laravel يملك `jobs` للطابور).
- START وقف عند الخطط — التنفيذ يدوي اسبرينت-اسبرينت.

---

## §C — Patterns to mirror (build X → copy Y; don't re-derive)

| Building… | Mirror (exact reference) |
|---|---|
| **Admin CRUD** (translatable) | `Admin/CountryController` + `Services/Admin/CountryService` + `Requests/Admin/Country/*` + `resources/views/admin/countries/` + `config/sidebar_routes.php` + lang. Extend `AdminBaseController`. |
| **Admin CRUD** (with media/upload) | mirror `Slider` (model `app/Models/Slider.php` uses media) + its admin controller/views. |
| **API multi-endpoint flow** | `Api/V1/Auth/*` (base) **أو** Daleel: `Api/V1/User/Auth/*` + `Api/V1/Provider/Auth/*` + `UserAuthService` / `ProviderAuthService` + token داخل `UserResource` / `ProviderResource`. |
| **Admin hiring + reports** | `Admin/{JobCategory,Skill,Provider,JobPost,JobApplication,Interview,Plan,Subscription,CandidateRequest}Controller` + `Services/Admin/*` + `resources/views/admin/{jobcategories,…}` · home: `DashboardHomeService` · reports: `ReportService`. |
| **Support APIs (reuse)** | `ComplaintApiService` · `Api/V1/{User,Provider}/Support/ComplaintStoreController` · `Api/V1/{User,Provider}/Notifications/IndexController`. |
| **Billing (no gateway)** | `Api/V1/{User,Provider}/Billing/*` + `Services/Billing/BillingService` · PlanResource/SubscriptionResource · اشتراك morph واحد نشط (trial/active). |
| **Jobs + applications** | `Api/V1/User/Jobs/*` + `Provider/Jobs/*` + `Services/Hiring/*` · نشر 3 خطوات draft→ترجمة→active · 409 للتقديم المكرر. |
| **Seeker profile sections** | `Api/V1/User/Profile/*` + `Services/Profile/*` + ملكية عبر Form Request `authorize()` + `profile_completion` من `UserProfileService::recalculate()`. |
| **API single-entity + resource** | `Api/V1/CountryController` + `Resources/Api/V1/CountryResource` + `CountryCollection` (pagination via `PaginationTrait`). |
| **Model — translatable** | `app/Models/Country.php` (+ `CountryTranslation`, `*_translations` table). Hiring: `JobPost` / `Plan` / `JobCategory` / `Skill`. |
| **Model — auth-style** (login) | `app/Models/User.php` (`BaseAuthModelTrait`, `HasApiTokens`, `SoftDeletes`, hashed password). Provider: `app/Models/Provider.php`. |
| **Multi-audience auth** (provider/delegate/company) | **default = model + Sanctum guard per audience** (mirror `admins`) → `docs/build/build-auth-audience.md`. |
| **OTP / verification flow** | `app/Services/Otp/OtpService.php` (`sendOtp`/`verifyOtp`/`failActiveOtps`) + `OtpType` (`OLD_*/NEW_*` for credential changes). |
| **Side effects** (job/event/observer/notification) | `docs/build/build-side-effects.md` (base: `app/Jobs/SendNotificationJob.php`, `app/Notifications/UserNotification.php` + `FirebaseV1Trait`). Payload: `title`/`message` `{ar,en}` + `notification_type` + entity ids. Devices: `DeviceService::sync` on auth + `User`/`Provider::devices()`. |
| **Response envelope** | `app/Traits/Response/*` — never a custom shape. |
| **Enum** | `app/Enums/LoginType.php` (`use GeneralEnumTrait` + `const PATH`). |

> The **build playbooks** (`docs/build/*`) own the full "how"; this table just points you at the **live
> reference file** to copy so you skip the hunt. When in doubt on a convention, read the sibling first.
