مراجعة سيرو (auth/otp/): مصر تستعمل Kazumi SMS مع failover لواتساب، وسوريا/الأردن Nabeh. عندنا كان مزوّد واحد فقط. - integrations/otp/: واجهة OtpProvider + OtpDispatcher يوجّه حسب tenant.countryPack بسلسلة failover (eg: [kazumi, nabeh] · jo/sy: [nabeh]) - KazumiSmsProvider (مصر SMS) + NabehOtpProvider (غلاف على NabehService) - كل مزوّد يرسل رمزاً نولّده نحن (Redis) — استبعدنا نمط Intaleq (يولّد الرمز بنفسه) حفاظاً على مصدر واحد للرمز - موحَّد: AuthService.sendOtp و PayoutsService.issueOtp يمرّان بنفس المُوزِّع الآن — أُزيل كل استدعاء Nabeh مباشر. أي مسار يحتاج رسالة يستدعي الخدمة الموحّدة (طلب المالك) - فشل السلسلة كاملة = ServiceUnavailable صريح، لا صمت قرار المالك (2026-07-17): بلا كلمة مرور إطلاقاً. المصادقة = هاتف + OTP مرة → جلسة مربوطة بالجهاز (D2). التسجيل بالهاتف لا Google/Apple (محظوران في بعض الدول). سيرو نفسه لا كلمة مرور حقيقية له (password = hash(email) وهمي، ومقارنة نصّية غير آمنة في مسار التجربة). يطابق أوبر/كريم/inDrive. مراجعة حدّ الطلبات في سيرو (RateLimiter.php): حدود مسمّاة لكل نوع + fallback بملف عند تعطّل Redis (fail-closed). عندنا مسار OTP fail-closed أصلاً؛ تخزين Throttler على Redis مؤجَّل للتوسّع الأفقي الفعلي (موثّق في D4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
29 lines
1.0 KiB
TypeScript
29 lines
1.0 KiB
TypeScript
import { Global, Module } from '@nestjs/common';
|
|
import { NabehModule } from '../nabeh/nabeh.module';
|
|
import { OtpDispatcher } from './otp-dispatcher.service';
|
|
import { OTP_PROVIDERS } from './otp-provider.interface';
|
|
import { NabehOtpProvider } from './providers/nabeh.provider';
|
|
import { KazumiSmsProvider } from './providers/kazumi.provider';
|
|
|
|
/**
|
|
* توجيه OTP متعدد المزوّدين (docs/17 — D5). عالمي: `OtpDispatcher` يُستدعى من
|
|
* كل مسار يرسل رمزاً. لإضافة مزوّد: أضِف موفّره هنا وسجّله في مصفوفة
|
|
* `OTP_PROVIDERS` وأضِف اسمه لسلسلة دولته في `otp-dispatcher.service.ts`.
|
|
*/
|
|
@Global()
|
|
@Module({
|
|
imports: [NabehModule],
|
|
providers: [
|
|
NabehOtpProvider,
|
|
KazumiSmsProvider,
|
|
{
|
|
provide: OTP_PROVIDERS,
|
|
useFactory: (nabeh: NabehOtpProvider, kazumi: KazumiSmsProvider) => [nabeh, kazumi],
|
|
inject: [NabehOtpProvider, KazumiSmsProvider],
|
|
},
|
|
OtpDispatcher,
|
|
],
|
|
exports: [OtpDispatcher],
|
|
})
|
|
export class OtpModule {}
|