# 🔧 م2 (Settings & Founding Permissions) — RESUME / execution contract

**STATUS: 🧊 FROZEN 2026-07-02 (تحويل لتعديل عاجل في اللاب — نرجع نكمّل م2 من هنا).** م0 ✅ معتمدة · م1 ✅ معتمدة (شاشة الأطباء CRUD الكامل مؤجّلة رسميًا لـ م3). م2 في منتصف التنفيذ.

---
## 🧊 نقطة التجميد — الحالة الدقيقة عند الرجوع (2026-07-02)

### اللي اتعمل فعلاً
- **WP-A (BE settings backbone) = DONE + reviewed + fix committed pending re-review.**
  - Implemented: `ClinicSettingDefinitionSeeder` (18 defs/6 مجموعات) · `SettingValidatorRegistry` (Core) · `ClinicSettingValidator` · wired `SettingsService::set` · `PUT /core/settings/bulk` (validate-all→write-all atomic + cache flush) · 12 Pest. Base commit **`fdf845057`** على `hazemdev` (BE = الريبو الشغّال → الكود LIVE على moonui_dev_be).
  - Reviews: native = Spec ✅ / Quality **APPROVED** (0 Critical/blocking) · Codex = CHANGES-NEEDED.
  - **Fix agent شغّال/خلص** (id a87b857dcd416c7a3) — 5 إصلاحات: (١) **`default_payment_method` per-company** (يقرا `LabPaymentMethod::activeKeys($companyId)` زي `CollectReceptionReceipt:164`؛ **قرار Fable = A**) (٢) gate الـ SettingsService static fallback على `resolve()===null` (مطلوب لعمل #1) (٣) strict boolean يرفض `'true'/'false'` (٤) تست cache-flush يأكّد flush واحد post-commit (٥) تست 403 لبوابة `core.settings.manage`. **⚠️ عند الرجوع: أكّد commit الـ fix على hazemdev (`git log`) → أعد المراجعة (native+Codex) → علّم WP-A complete.**
  - **✅ اتشغّل الـ seeder على moonui_dev_be** (المالك طلب يشوفهم): 18 تعريف متأكدين — clinic_financial:2 · clinic_modes:5 (ordering/lab_mode/rad_mode/pharmacy_source/his.mode) · clinic_operations:6 · clinic_print:5 · (prescription/clinical placeholder فاضيين). ظاهرين على `/app/clinic/settings` بالشكل الخام (generic).
- **WP-E (FE appCan sweep) = DONE + reviewed + fix committed pending re-review.**
  - Implemented: 72 حارس `*appCan` في 25 شاشة، مطابقين لصلاحيات routes الـ BE. Base commit **`7b8b497`** على `hazemdev`. Build أخضر. coverage table في `wp-e-coverage.md`. **⛔ مش منشور على /app** (committed بس؛ ينشر مع باقي FE م2 في النهاية).
  - Reviews: native = Spec ⚠️(gap 1) / Quality Changes-needed · Codex = CHANGES-NEEDED.
  - **Fix agent شغّال/خلص** (id a5db6453e02ae847a) — (١) **`startConsultation` حارس مشروط** `appt.encounter_id ? 'clinic.encounters.view' : 'clinic.encounters.create'` (كان يقفل الدكتور بره الكشف) (٢) حارس Save في `external-result-dialog` (٣) تنسيق. **⚠️ عند الرجوع: أكّد commit الـ fix → build → أعد المراجعة → علّم WP-E complete.**

### قرارات Fable المحسومة في هذه الجولة (لا تُعاد)
1. **`default_payment_method` = per-company NOW** (option A): validator يقرا `activeKeys($companyId)` (fallback DEFAULT_KEYS لو فاضية، زي الكاشير) · يفضل `allowed_values=DEFAULT_KEYS` على التعريف كـ display fallback · FE (WP-B) الـ dropdown يجيب خياراته من طرق دفع الشركة · **م4 note:** المستهلك لازم يـ fallback لو الديفولت المحفوظ بقى غير نشط (سجّل في spec م4).
2. **نقل الـ seeder من Core لـ Clinic = CONFIRMED keep** (كل موديول بيملك seeder إعداداته؛ Core-ownership كان شذوذ الكلينك). idempotent (`updateOrCreate` على `setting_key`) + مربوط في `ClinicDatabaseSeeder`. ⏳ follow-up deploy: أكّد MoonStack update بيشغّل `ClinicDatabaseSeeder` قبل ما الكلينك يروح لأي عميل (مش بلوكر لـ moonui).

### الباقي في م2 (الـ DAG من نقطة الرجوع)
1. **اجمع نتايج الـ2 fix agents** (WP-A + WP-E) → **أعد المراجعة native+Codex لكل واحد** → علّم complete في الـ ledger.
2. **WP-C (BE roles):** `ClinicRoleController` + `catalog()` (كلون `LabRoleController`) + الـ**6 presets** في `ClinicPermissionDependencies::presets()` (استقبال/تمريض/دكتور-مساعد/كاشير/مدير/طبيب-العيادة — القوايم في `fable-ruling.md` Ruling 4b) + generalize `RoleSaveService` `lisOnly`→prefix-confined (back-compat + regression Pest) + Pest. على `core.roles.*` — صفر صلاحية جديدة. (يعتمد على WP-A.)
3. **WP-B (FE settings screen):** hybrid — group registry ثابت 6 مجموعات + per-key decoration + الـ4 modes كـ **radio-cards** + **account-picker** للحسابات + **`default_payment_method` dropdown ديناميكي** (من طرق دفع الشركة) + كروت placeholder (prescription/clinical) + الحفظ عبر `PUT /core/settings/bulk` + **الرفض inline 422** (fail-fast). (يعتمد على بوابة WP-A.)
4. **WP-D (FE roles screen):** كلون `lis-roles.component` → route `/his/roles` + preset chips + dependency auto-tick. (يعتمد على WP-C + WP-B.)
5. **Integration smoke + owner-test dry-run على co4:** اقلب `lab_mode`→بادج على شاشة الخدمات (بادج جزء من WP-B) · احفظ `ar_account_id` فاضي→422 inline · اعمل دور «تمريض» من preset→ادخل بيوزره→طابور+قياسات بس. ثم **build FE واحد + deploy /app** (WP-B+WP-D+WP-E مع بعض) + CHANGELOG ثنائي + push hazemdev→main + حدّث سجل التقدم → **المالك يتست م2 ويعتمد**.

### حالة النشر عند التجميد (مهم)
- **BE:** كود WP-A **LIVE** على moonui_dev_be (الريبو الشغّال hazemdev) + الـ seeder اتشغّل (18 defs). fix WP-A هيبقى live أول ما يـ commit (BE=repo). **مش مدفوع لـ main.**
- **FE (`/app`):** **مـا اتغيّرش** — حُرّاس WP-E committed على hazemdev بس **مش مبنيين/منشورين**. الإعدادات الـ18 بتظهر على الشاشة القديمة لأنها داتا BE. أول build+deploy FE هيكون في نهاية م2 (WP-B+D+E سوا).
- **صفر migrations** في م2 كله (seeder بس). **⛔ لا cp لعملاء/staging.**

---

## المنهجية الملزمة (المالك 2026-07-02)
- **Opus ينفّذ · Fable الأدفايزور** — «استخدم agents في كل حاجة + شاور Fable في كل قرار» (تعليمة المالك الحرفية).
- SDD: منفّذ → مراجع مستقل → بوابة **native + Codex** لكل WP · TDD جوّا كل WP · **`frontend-design` skill لكل شاشة**.
- نشر: **moonui `/app` فقط** · ⛔ لا cp لعملاء/staging · **صفر migrations** (seeder بس) على `moonui_dev_be` بإذن · CHANGELOG ثنائي · **سجل التقدم في `topics/clinic-execution-phases.md` + HTML يتحدث مع كل خطوة**.
- تعريف الإتمام: المراجعة عدّت (صفر Critical/Important) + build/Pest خضراء + **المالك تست بسيناريو م2 واعتمد**.

## المدخلات (كلها هنا في نفس المجلد — للاستئناف البارد)
- `fable-ruling.md` — **حكم Fable الكامل = عقد التنفيذ** (Ruling 1..7 + مصفوفة الإعدادات بمفاتيحها + الـ6 presets بصلاحياتها + WP DAG + red flags). اقرأه أولًا.
- `scout-a-be-settings.md` · `scout-b-fe-settings.md` · `scout-c-perms-roles.md` · `scout-d-kb-spec.md` — خرايط الحالة الحالية (file:line).

## خلاصة قرارات Fable (المرجع الكامل في fable-ruling.md)
1. **الإعدادات (D1):** 12 تعريف جديد + ترقية 2 عبر 6 مجموعات. المجموعات: `clinic_financial` (2 GL + fail-fast) · `clinic_modes` (`ordering_mode` موجود + `lab_mode`/`rad_mode` = **`integrated\|standalone`** default `integrated` + `pharmacy_source`=`products\|standalone_formulary` + ترقية `his.mode`=`single_clinic\|center`) · `clinic_operations` (`allow_overbooking` موجود + `scheduling_mode`=`slots\|open` + `default_payment_method`=قيم إيصال موجودة + `allow_credit_balance` + `followup_window_days` 0-365 def 14 + ترقية `dashboard_top_services_count`) · `clinic_print` (5 مفاتيح shell: header/footer/show_logo/show_diagnosis/paper_size) · `clinic_prescription` (**placeholder card** — مصدر الدواء = نفس `pharmacy_source`) · `clinic_clinical` (**placeholder + link** للـ history-questions).
   - **⛔ تأثير `lab_mode` في م2 = minimal:** يتخزن + helper text + **بادج واحد على شاشة خدمات م1** (standalone→أبرز CTA الاستيراد؛ integrated→hint). **صفر سلوك** (routing/picker = م7). ده أخطر scope trap.
   - **مؤجّل:** refund/variance GL→م8 · `visit_stations`+queue-reset→م5 · توقيع الطبيب = بيانات دكتور مش setting · سعر الإعادة = سعر variant م1 مش setting (بس النافذة setting) · مفاتيح الروشتة→م7 · محرك الحقول→م6.
2. **التخزين والشاشة (D2):** `ClinicSettingDefinitionSeeder` جديد (كلون LIS، ينقل الـ4 صفوف الموجودة جواه) · FE **hybrid** (group registry ثابت 6 مجموعات + per-key decoration؛ الـ4 modes كـ radio-cards؛ المفاتيح الجديدة تظهر بلا كود FE — مبدأ «عميل جديد بلا كود») · مش hand-built form.
3. **الـ Validation (D3):** Core `SettingValidatorRegistry` (مرآة `PermissionDependencyRegistry`) + `ClinicSettingValidator` + **`PUT /core/settings/bulk`** (validate-all→write-all في transaction واحدة، 422 map لكل key). GL required + حساب detail مملوك للشركة · integers min/max بلا سالب · undefined key مرفوض · enum `InvalidArgumentException`→**422 مش 500** (تست المالك بيقول «يرفض»؛ 500 يفشله).
4. **الأدوار (D4):** كلون LIS (`ClinicRoleController::catalog` + شاشة `/his/roles`) على **`core.roles.*` — صفر صلاحية جديدة** · `RoleSaveService` `lisOnly`→prefix-confined مع back-compat · **6 presets templates مش seeded roles:** استقبال · تمريض (`vitals.record`+`queue.view` بس) · دكتور مساعد (`history.record`+`queue.view` بس) · كاشير (`payments.create/void`+`cashier.*`+`orders.view`+`ledger.view`) · مدير (كل `clinic.*`+`core.settings.view` بلا manage/roles) · **طبيب العيادة** (موجود، نبقيه؛ +`lab-orders.create`+`rad-orders.create`+`results.external`). **إلزامي: E2E walk لكل preset** (مش paper-validation).
5. **appCan sweep (D5):** **كامل الآن** (تست المالك #3 «حدود التمريض» load-bearing عليه). انضباط: route→perm mapping table من `routes/api.php` أولًا → احرس terminal actions مش بس dialog triggers → coverage table للبوابة. المراحل اللي تعيد بناء شاشات ترث الحراسة.
6. **WP DAG (D6):** **BE: WP-A (settings seeder+validator+bulk) → WP-C (roles)** ‖ **FE: WP-E (appCan sweep، يبدأ فورًا) → WP-B (شاشة الإعدادات، تنتظر بوابة WP-A) → WP-D (شاشة الأدوار، تنتظر WP-C)** → integration smoke → **owner-test dry-run على co4**. كاتب واحد لكل ريبو. **صفر migrations.**
7. **تصعيدات المالك (D7 — 3 خفيفة):** (١) سقف المدير (كل clinic + يشوف الإعدادات، بلا manage/roles). (٢) إبقاء preset «طبيب العيادة» السادس. (٣) الكاشير يسترد/يلغي بنفسه (`payments.void`) بلا موافقة مدير. **الديفولت ينطبق لو المالك وافق.**

## سيناريو تست المالك لـ م2 (يقفل المرحلة)
(١) اقلب `lab_mode` standalone → البادج يظهر على شاشة الخدمات (وقيمته تفضل بعد reload). (٢) احفظ `ar_account_id` فاضي → 422 inline نظيف بالعربي (مش 500). (٣) اعمل دور «تمريض» من الـ preset → ادخل بيوزره → يشوف الطابور + القياسات بس، الباقي مخفي/مرفوض.

## Red flags (من الحكم — إلزام)
⛔ ماتوصّلش أي mode effect (routing/picker/intents/EncounterResource) · appCan mis-guard = regression (زرار مخفي عن مستخدم شرعي أسوأ من غير محروس) → الـ mapping table + مراجعة perm↔route إلزامية · الـ500 trap (enum violation لازم 422) · cache flush بعد bulk save (وإلا البادج ما يتحركش 5 دقايق) · `RoleSaveService` refactor مايخربش حفظ أدوار LIS (regression Pest) · preset ناقص صلاحية non-clinic يبوّظ الـ workflow (E2E walk) · تجاهل ترقيم `clinic-service-settings.md` القديم.

## ▶️ الاستئناف
اقرأ `fable-ruling.md` → أكّد الـ3 تصعيدات مع المالك (لو مش متأكدين) → اكتب بريفات SDD للـ WPs → نفّذ BE track (A→C) ‖ FE track (E→B→D) ببوابة native+Codex لكل واحد → integration smoke → owner dry-run → seed على moonui_dev_be + deploy /app + CHANGELOG + push + حدّث سجل التقدم.
