feat: N1 — خدمة اللوحات + فرض تعليق المستأجر + النظرة الشاملة

- اللوحات الثلاث تُخدم من نفس أصل الـAPI (/panel/{superadmin,admin,service})
  عبر useStaticAssets + bind mount، فترث TLS القائم بلا دومين ولا CORS.
- تعليق المستأجر كان زخرفة: tenant.status يُكتب ويُعرض بلا أي فرض. الآن
  يُفرض في JwtStrategy (نقطة واحدة) + AuthService.resolveTenant، مع إبطال
  الكاش ليسري فوراً، وتمرير عند تعذّر القراءة حتى لا تسقط المنصة كلها.
- GET /admin/overview: رحلات · GMV · إيراد المنصة لكل مستأجر باستعلام
  واحد مجمَّع (لا N+1).
- توثيق قرار طبقات التطبيق (const flags + tree-shaking · أصيل موحّد
  لـShorebird · طبقتا الإعداد) في docs/22 §1.5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-18 12:35:20 +03:00
co-authored by Claude Fable 5
parent 5cad6adbde
commit 3ab74a13a8
12 changed files with 343 additions and 15 deletions
+4
View File
@@ -37,6 +37,10 @@ export class AuthService {
private async resolveTenant(slugOrId: string): Promise<Tenant> {
const tenant = await this.tenantsService.resolve(slugOrId);
if (!tenant) throw new UnauthorizedException('Unknown tenant');
// المستأجر المعلَّق يُمنع من الباب (docs/22 — N1): هذه النقطة تخنق
// `sendOtp` و`verifyOtp` معاً، فلا يُرسَل رمز أصلاً لمستأجر موقوف.
// الطلبات المصادَقة القائمة يقطعها `JwtStrategy` بالتوازي.
if (tenant.status !== 'active') throw new UnauthorizedException('tenant_suspended');
return tenant;
}