feat: D5 — OTP متعدد المزوّدين حسب الدولة (من سيرو) + قرار بلا كلمة مرور
مراجعة سيرو (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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c258a8c4b8
commit
8f6c46f0ac
@@ -0,0 +1,28 @@
|
||||
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 {}
|
||||
Reference in New Issue
Block a user