# LEDGER — Permissions Screen Redesign + Enforcement Hardening

**Feature:** إعادة تصميم شاشة الصلاحيات `/core/roles` + كتالوج وصف الصلاحيات (BE) + تصليب تطبيق الصلاحيات في الواجهة (بالأولوية) + قاعدة «الإعداد ياخد صلاحيته».
**Date started:** 2026-07-13
**Install:** moonui2 · BE `/home/moonui2/moon-erp-be` (branch `hazemdev2`) · FE `/home/moonui2/public_html/moon-erp` · Dev DB `moonui2_dev_be` (⛔ never fresh/wipe).
**Source plan (approved):** `knowledge-base/plans/permissions-screen-redesign-analysis.html`
**Companion analysis:** `knowledge-base/plans/convert-buttons-permission-analysis.html` (convert-button gaps fold into WP4b/WP4c).

## 🎯 GOAL (owner acceptance test — do NOT stop until met)
> النظام كله شغّال صح: (1) شاشة `/core/roles` الجديدة (مصفوفة مورد×إجراء + info لكل صلاحية + coverage lint + قوالب + وضع «حسب الشاشة» + شارة «API فقط» للـ144) تظهر وتُحفظ صح على `/app` الحيّ؛ (2) كتالوج وصف الصلاحيات يخدم الشاشة عبر `GET /core/permissions`؛ (3) البوابات الخشنة أُنزلت لمستوى الإجراء بالترتيب: محاسبة ← مبيعات ← مشتريات ← مخزون ← إنتاج ← HR ← الباقي (الخطير/المالي أولًا داخل كل موديول) — وما لم يُغطَّ **مُسجَّل** لا مُدّعى اكتماله؛ (4) قاعدة «الإعداد ياخد صلاحيته» مطبّقة (عمود `permission` على `setting_definitions` يُفحَص لكل إعداد) + سدّ فجوة `*.settings.manage` الثمانية؛ (5) باگ `hrm.training` مُصلَّح. كل WP: Codex + (Fable على [FIN]/محوري) + اختبار أخضر مقابل الأساس + build أخضر + نشر `/app` بعد أي FE. لا merge/main (المالك بيعمل `/fullpush`). الاكتمال يُؤكَّد بالتشغيل/الاختبار.

## Decisions (approved — do NOT re-litigate)
1. **مصدر الوصف = كتالوج BE** يعمّم `LisScreenCatalog` (`label_ar/en, desc_ar/en, danger, kind, screen`)، مع fallback FE للـi18n ثم الاسم المركّب.
2. **ترتيب WP4** = محاسبة(مالي) ← مبيعات ← مشتريات ← مخزون ← إنتاج ← HR ← الباقي (LIS/core/pos/clinic). داخل كل موديول: الخطير/المالي أولًا (delete/approve/post/convert). مرحلي؛ سجّل ما لم يُغطَّ.
3. **الـ144 «بلا واجهة»** تظل قابلة للمنح بشارة «API فقط — لا شاشة بعد» (لا تُخفى).
4. **قاعدة الإعدادات** = عمود `permission` على `setting_definitions` يُفحَص لكل إعداد + سدّ فجوة `*.settings.manage` الثمانية (accounting, inventory, crm, nphies, einvoicing, pos, production, clinic) + توثيق العُرف.
5. **طرح المصفوفة** = استبدال كامل للقائمة المسطّحة، مع الحفاظ على كل الموجود (القوالب/الاسم/النطاق/الصفحة الرئيسية/تبويب المنيوهات/module-activation).

## WP table
| WP | Scope (dense) | Repo | Depends | Review | Migration? | Status | Commits |
|----|---------------|------|---------|--------|-----------|--------|---------|
| WP1 | 🔄 كتالوج الصلاحيات BE: **PHP `PermissionCatalog` class** (يعمّم LisScreenCatalog، لا migration — أقل خطرًا) يوفّر label/desc/danger/kind/resource/screen لكل صلاحية؛ يبدأ محاسبة+مبيعات+مشتريات+core؛ إثراء `GET /core/permissions` بدمج الميتاداتا. Fallback للصلاحيات غير الموصوفة. | BE | — | Codex+Fable | no (PHP catalog) | ✅ done | `0a587a82`+`671aae0d6` · new test 5/5, re-run 71/0 · Codex clean · Fable 6 danger+1 soften applied |
| WP2 | 🔄 إصلاحات دقيقة: تصحيح بوابة `hrm.training` المعلّقة (FE) + إضافة `<module>.settings.manage` للـ8 موديولات الناقصة (BE seeder). | BE+FE | — | Codex | no (seeder) | ✅ done | BE `dc54c0db6` (8× settings.view+manage) · FE `9c3a36749` (hrm.training gate) · 13 tests green · Codex clean · seeded to dev · /app deployed |
| WP5 | 🔄 قاعدة الإعدادات: عمود `permission` على `setting_definitions` + فحص لكل إعداد في مسار الكتابة + توثيق العُرف. [FIN-schema] | BE | WP2 | Codex+Fable | yes | 🔄 started 2026-07-13 | |
| WP3 | إعادة تصميم `/core/roles` (FE): مصفوفة مورد×إجراء + شريط وحدات + بحث/فلاتر + قوالب + info popover + coverage lint + وضع «حسب الشاشة» + شارة «API فقط». يستهلك كتالوج WP1 + fallback. استبدال كامل. | FE | WP1 | Codex+Fable | — | ⬜ | |
| WP4a | تصليب محاسبة (87 خشنة): إنزال `*appCan` لمستوى الإجراء — delete/approve/post أولًا. سجّل غير المُغطّى. | FE | WP1 | Codex | — | ⬜ | |
| WP4b | تصليب مبيعات (incl. أزرار التحويل من convert-buttons). | FE | WP1 | Codex | — | ⬜ | |
| WP4c | تصليب مشتريات (incl. أزرار التحويل). | FE | WP1 | Codex | — | ⬜ | |
| WP4d | تصليب مخزون (الخازن). | FE | WP1 | Codex | — | ⬜ | |
| WP4e | تصليب إنتاج. | FE | WP1 | Codex | — | ⬜ | |
| WP4f | تصليب الموارد البشرية. | FE | WP1 | Codex | — | ⬜ | |
| WP4g | تصليب الباقي (LIS/core/pos/clinic) بالتوصية؛ سجّل ما تبقّى خشنًا. | FE | WP1 | Codex | — | ⬜ | |

## DAG / serialization
- **BE writers (serialize):** WP1 → WP2(BE part) → WP5. One writer per repo at a time.
- **FE writers (serialize):** WP2(FE nav fix) → WP3 → WP4a → … → WP4g. Never two FE sub-agents concurrently.
- BE and FE WPs may interleave but each repo has one writer at a time.
- WP3 & WP4* depend on WP1 (catalog endpoint shape for WP3; WP4 only needs the FE gate patterns — independent of WP1 in practice, but sequenced after to keep one FE writer).

## Baseline (pre-existing test state — recorded 2026-07-13)
Ran (sqlite): RoleApiTest, RoleLifecycleTest, AdditiveRolePermissionsTest, Wp8aActionPermissionsTest, SettingApiTest, SetupPermissionTest → **8 failed / 87 passed**. Pre-existing failures (NOT ours — do not blame):
1. `RoleLifecycleTest::C2: another company role is invisible in both role indexes` — tenant-scoping (pre-existing).
2. `SettingApiTest` ×7 (can list/filter definitions, list/get/update settings, idempotent) — ALL fail with `UniqueConstraintViolationException` on `setting_definitions.setting_key`: **`accounting.ar_parent_account` is seeded TWICE in `SettingDefinitionSeeder`**. → WP5 touches this seeder; fix the duplicate as part of WP5 (these 7 should go GREEN after WP5).
- FE: `ng build` green pre-start → **CONFIRMED green 2026-07-13** (only benign html2canvas CommonJS warning).

## Deferrals (discovered mid-flight — starts empty)
- (none yet)

## Progress log
- 2026-07-13: Phase A started — workspace + LEDGER created; baseline running.

- 2026-07-13: WP1 🔄 started (PermissionCatalog + enrich /core/permissions).
- 2026-07-13: WP1 ✅ done. PermissionCatalog (326 keys, Core/Acc/Sales/Purch) + enriched /core/permissions (backward-compat). Codex: clean/Low. Fable [FIN]: 6 danger overrides (fx-revaluation.run, transfers.create, petty-cash.create, ar-ap.create, checks-issued/received.change-status, opening-balances.confirm) + softened sales.quotations.reject — applied & tested (5/5). Baseline preserved (71/0 on re-run files). SHAs 0a587a82, 671aae0d6.
- 2026-07-13: WP2 🔄 started (hrm.training gate fix + 8× settings.manage).
- 2026-07-13: WP2 ✅ done. hrm.training menu retargeted to real training .view perms (both nav sources); 8× <module>.settings.view+manage seeded (accounting/inventory/crm/nphies/einvoicing/pos/production/clinic) — additive, seeded into moonui2_dev_be. 13 BE tests green; FE build green; /app deployed. Codex clean (5/5). SHAs BE dc54c0db6, FE 9c3a36749.
- 2026-07-13: WP5 🔄 started (setting_definitions.permission column + de-dupe seeder + per-setting enforcement).