feat: المجموعة K — استحقاقات الاشتراك مفروضة على السيرفر
القاعدة (docs/19): علم الميزة في التطبيق قرار عرض لا حدّ أمني. من يفكّك التطبيق ويفعّل الأعلام يرى الشاشة ثم يصطدم بـ403 من FeatureGuard. - K1: FeatureGuard + @RequiresFeature — tenant_id من التوكن الموقَّع لا من ترويسة. الوحدة عالمية عمداً: إجبار كل وحدة على استيرادها = نقطة منسيّة يوماً ما، والمنسيّة ميزة مجانية للجميع - K2: كتالوج الميزات + افتراضات الباقات. الافتراض هو المنع (قائمة بيضاء): ميزة جديدة تبقى محجوبة حتى تُمنح صراحةً - K3: GET /admin/features · GET /admin/tenants/:id/entitlements · PATCH /admin/tenants/:id/subscription — يدمج features لا يستبدلها (استبدالها كان سيمحو المشتريات السابقة) ويُبطل الكاش فوراً - K4: drivers_max عند apply — عند الإنشاء فقط، فسائق قائم لا يُطرد بتغيير باقة - K5: /tenant/config يرجع الاستحقاقات المحسوبة لا features الخام (الخام تجاوزات فقط فكان سيُظهر ميزات الباقة مطفأة) - K6: اختبار أن الترويسة لا تزوّر المستأجر + أن الافتراض منع لا سماح - K7: السيادة = كل الميزات — المستأجر يملك السيرفر فالحجب هناك وهم لا حماية محروس: dispatch · chat · payments/charge. المدفوعات لكل نقطة لا للصنف — الـwebhook بلا JWT فحارس الصنف كان سيمنعه. seed: المستأجر التجريبي siro صار sovereign (قرار المالك: أول مشترك بالباقة الكاملة) — وأيضاً يمنع حجب dispatch وحدّ 500 سائق من إسقاط سكربتات التحقق. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d9b0faab2d
commit
aae01fc4ee
+16
-10
@@ -214,19 +214,25 @@
|
||||
|
||||
---
|
||||
|
||||
## المجموعة K — الاستحقاقات ومنع تفعيل الميزات بلا اشتراك
|
||||
## المجموعة K — الاستحقاقات ومنع تفعيل الميزات بلا اشتراك — ✅ منفَّذة
|
||||
> **المستند الكامل: [19-entitlements-licensing](19-entitlements-licensing.md).**
|
||||
> القاعدة: **علم الميزة في التطبيق قرار عرض لا حدّ أمني.** الحدّ الحقيقي حارس على السيرفر.
|
||||
|
||||
| # | البند |
|
||||
|---|-------|
|
||||
| K1 | `FeatureGuard` + `@RequiresFeature()` — الاستحقاقات من Redis والقاعدة احتياط |
|
||||
| K2 | كتالوج الميزات + افتراضات لكل باقة |
|
||||
| K3 | نقاط سوبر-أدمن: إنشاء مستأجر باشتراك · تعديل الاستحقاقات · إبطال الكاش |
|
||||
| K4 | فرض الحدود العددية (`drivers_max`, `cities_max`) على السيرفر |
|
||||
| K5 | `GET /tenant/config` — `features` للعرض فقط، موثّقة صراحةً أنها ليست حدّاً أمنياً |
|
||||
| K6 | اختبار عزل في CI: مستأجر بلا ميزة يأخذ 403 على كل نقاطها |
|
||||
| K7 | قرار وضع السيادة: كل الميزات مشمولة + بند تعاقدي (لا وهم حماية تقنية) |
|
||||
| # | البند | الحالة |
|
||||
|---|-------|--------|
|
||||
| K1 | `FeatureGuard` + `@RequiresFeature()` — الاستحقاقات من Redis والقاعدة احتياط. الوحدة **عالمية** عمداً: إجبار كل وحدة على استيرادها يعني نقطة منسيّة يوماً ما، والمنسيّة ميزةٌ مجانية للجميع | ✅ |
|
||||
| K2 | `common/entitlements/features.ts` — الكتالوج + افتراضات كل باقة. **الافتراض هو المنع**: قائمة بيضاء، وميزة جديدة تبقى محجوبة حتى تُمنح | ✅ |
|
||||
| K3 | `GET /admin/features` · `GET /admin/tenants/:id/entitlements` · `PATCH /admin/tenants/:id/subscription` (يدمج `features` لا يستبدلها، ويُبطل الكاش فوراً) | ✅ |
|
||||
| K4 | `drivers_max` يُفرض عند `drivers.apply` — عند الإنشاء فقط، فسائق قائم لا يُطرد بتغيير باقة | ✅ (`cities_max` معرَّف بلا نقطة إنفاذ بعد) |
|
||||
| K5 | `GET /tenant/config` يرجع **الاستحقاقات المحسوبة** لا `features` الخام (الخام تجاوزات فقط، فكانت ستُظهر ميزات الباقة مطفأة) — موثّقة كعرض لا حماية | ✅ |
|
||||
| K6 | `feature.guard.spec` + `features.spec` — منها اختبار أن الترويسة لا تزوّر المستأجر، وأن الحارس يقرأ التوكن وحده | ✅ |
|
||||
| K7 | السيادة = كل الميزات بلا حدود، قراراً مقصوداً (لا وهم حماية تقنية) | ✅ |
|
||||
|
||||
**نقاط محروسة الآن**: `dispatch` · `chat` · `payments/charge`. المدفوعات محروسة **لكل نقطة** لا على مستوى الصنف — الـwebhook يناديه المزوّد بلا JWT فكان حارس الصنف سيمنعه.
|
||||
|
||||
**تغيير مقصود على الـseed**: المستأجر التجريبي `siro` صار `sovereign` بدل `brand`. سببان: يطابق قرار المالك («سيرو أول مشترك، له الباقة الكاملة»)، ويمنع حجب `dispatch` وحدّ `drivers_max: 500` من إسقاط سكربتات التحقق (كل تشغيلة تحميل تُنشئ عشرات السائقين وهم يتراكمون).
|
||||
|
||||
**ما تبقّى للمجموعة K**: حارس دور المنصة على نقاط `admin/*` (مفتوحة حالياً — بند قائم قبل K أصلاً)، ونقطة إنفاذ لـ`cities_max`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user