feat: حارس السوبر-أدمن + سياسة الدين لكل مستأجر

PlatformGuard (x-platform-secret، مقارنة ثابتة الزمن) يحرس admin/tenants*
و admin/features و platform/*. بدونه كان أدمن أي مستأجر يرقّي اشتراكه بنفسه
— أي أن المجموعة K كلها كانت زينة. سرّ غير مضبوط = منع الجميع لا فتح الباب
(الإعداد الناقص خطأ تشغيلي شائع، وفتح الباب عنده أسوأ من إغلاقه).
admin/users/:id/role تبقى لأدمن المستأجر: نطاقها من التوكن، وليست نقطة منصة.

سياسة الدين لكل مستأجر (قرار المالك): كل مشغّل يحدّد كم ديناً يسمح به،
و0 خيار صريح = لا دين إطلاقاً.
- tenants.settings jsonb — سياسات تشغيل يحكمها المستأجر، منفصلة عن features
  (استحقاقات يحكمها السوبر-أدمن): «كيف تشتغل» مقابل «ماذا اشتريت»
- credit-policy.ts: debt_allowance + signup_bonus لكل عملة. الافتراضات
  صُحّحت لقيم المالك: 2 JOD · 200 SYP · 200 EGP (كانت 5/500/500)
- تُخزَّن موجبةً («كم ديناً أسمح؟») لا كأرضية سالبة — أوضح للمشغّل و0 بلا
  لبس في الإشارة
- PATCH /credit/policy لأدمن المستأجر؛ updateSettings يدمج عميقاً فلا يمحو
  سياسة أخرى، ويُبطل الكاش وإلا سرت السياسة القديمة حتى ساعة
- إعداد مكسور يسقط للافتراض لا لدين بلا حدّ. والصفر لا يُبتلع (فخّ ||)

هجرة: TenantSettings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-17 15:26:41 +03:00
co-authored by Claude Opus 4.8
parent aae01fc4ee
commit 91e1692457
16 changed files with 388 additions and 60 deletions
+5 -1
View File
@@ -232,7 +232,11 @@
**تغيير مقصود على الـseed**: المستأجر التجريبي `siro` صار `sovereign` بدل `brand`. سببان: يطابق قرار المالك («سيرو أول مشترك، له الباقة الكاملة»)، ويمنع حجب `dispatch` وحدّ `drivers_max: 500` من إسقاط سكربتات التحقق (كل تشغيلة تحميل تُنشئ عشرات السائقين وهم يتراكمون).
**ما تبقّى للمجموعة K**: حارس دور المنصة على نقاط `admin/*` (مفتوحة حالياً — بند قائم قبل K أصلاً)، ونقطة إنفاذ لـ`cities_max`.
**حارس السوبر-أدمن ✅**: `PlatformGuard` (`x-platform-secret`, مقارنة ثابتة الزمن) يحرس كل `admin/tenants*` و`admin/features` و`platform/*`. **سرّ غير مضبوط = منع الجميع** لا فتح الباب. حرجٌ لأنه بدونه يرقّي أدمن أي مستأجر اشتراكه بنفسه — أي أن K كلها كانت زينة. `admin/users/:id/role` تبقى لأدمن المستأجر (نطاقها من التوكن) لأنها ليست نقطة منصة.
**سياسة الدين لكل مستأجر ✅** (قرار المالك): `tenants.settings.credit` — `debt_allowance` و`signup_bonus` لكل عملة، يضبطهما أدمن المستأجر عبر `PATCH /credit/policy`. الافتراضات 2 JOD · 200 SYP · 200 EGP، و**0 خيار صريح = لا دين**. `settings` منفصلة عن `features` عمداً: تلك «ماذا اشتريت» (سوبر-أدمن)، وهذه «كيف تشتغل» (المستأجر). هجرة `TenantSettings`.
**ما تبقّى**: نقطة إنفاذ لـ`cities_max` (لا مفهوم «مدينة» مُدار بعد)، ونموذج مستخدم منصة حقيقي بدل السرّ المشترك.
---