پرش به محتویات

Domain و جریان درخواست OTP

Use Case RequestOTP یک Mobile معتبر را به Challenge کوتاه‌عمر تبدیل می‌کند و فقط پس از پذیرش پایدار آن، درخواست تحویل را به Adapter می‌دهد.

مدل دامنه

Mobile
: Value Object شماره موبایل ایران که ورودی‌های پشتیبانی‌شده را به قالب E.164 مانند +989121234567 تبدیل و نسخه Maskشده امن تولید می‌کند.

OTPChallenge
: Aggregate دارای شناسه UUIDv7، Digest کد، Hash سیگنال‌های کنترل سوءاستفاده، زمان انقضا، زمان ارسال مجدد و وضعیت چرخه عمر.

OTPRequestRatePolicy
: Policy محدودیت Mobile، Device، IP و Service که Repository باید به‌صورت Atomic اعمال کند.

جریان موفق

sequenceDiagram participant Client participant HTTP as HTTP Adapter participant App as RequestOTP participant Repo as PostgreSQL Adapter participant Delivery as OTP Deliverer Client->>HTTP: Mobile + Idempotency-Key + X-Device-ID HTTP->>App: ورودی Transport تاییدشده App->>App: Parse Mobile و ساخت OTP امن App->>Repo: Create با Challenge و Rate Policy Repo->>Repo: Lock، Rate Limit و Persist اتمیک Repo-->>App: Created یا Replay alt Challenge جدید App->>Delivery: Mobile + OTP Plaintext موقت end App-->>HTTP: Challenge امن برای پاسخ HTTP-->>Client: 202 Accepted

Transaction Boundary

Lockهای Advisory بر Scopeهای موثر گرفته می‌شوند، شمارنده‌های Rate Limit و Idempotency بررسی می‌شوند، Challenge فعال قبلی Invalid و Challenge جدید در یک Transaction ثبت می‌شود. Plaintext OTP هرگز وارد Command ذخیره‌سازی نمی‌شود.

تحویل Development پس از Commit انجام می‌شود. این مرز برای Adapter واقعی SMS کافی نیست، چون شکست Provider می‌تواند Challenge ذخیره‌شده ولی تحویل‌نشده بسازد. پیش از ملی‌پیامک باید Transactional Outbox به Transaction ایجاد Challenge اضافه شود.

مسیرهای جایگزین

  • Mobile نامعتبر پیش از ساخت Challenge رد می‌شود.
  • درخواست همسان با Idempotency Key قبلی بدون OTP جدید Replay می‌شود.
  • درخواست متفاوت با همان Key Conflict است.
  • عبور از هر Limit با Retry-After رد می‌شود.
  • خطای Repository یا Delivery پاسخ عمومی 503 می‌دهد و جزئیات داخلی فقط در Log پاک‌سازی‌شده می‌ماند.

آزمون لازم

  • Parse تمام قالب‌های Mobile پذیرفته و ردشده؛
  • یکتایی Replay و Conflict؛
  • Invalid شدن Challenge فعال قبلی؛
  • مرز انقضا و Resend؛
  • شکست Random Generator، Repository و Delivery؛
  • نبود Plaintext OTP در مدل Persistشده و Logهای غیر Development.