Skip to content

OTP and Email — Consolidated Planning

Purpose: Single reference for OTP flow, template ownership, formatting, Zuplo callers, email delivery, Resend migration, and templates.
Source: Merged from otp-email-flow, otp-email-newline-*, otp-email-readability, otp-email-zuplo-api, otp-input-ui, email-delivery-flow-verification-dashboard, email-resend-migration, email-templates-unified-design, feature-email-templates-frappe.


1. OTP Flow and Template Ownership

sequenceDiagram
  participant C as client-web
  participant Z as Zuplo Gateway
  participant A as Auth Worker
  participant Q as Queue
  participant M as Mail sender
  participant R as Resend

  C->>Z: POST /auth/otp/request {email}
  Z->>A: forward
  A->>A: USER_MAP check, OTP gen, AUTH_STORE.put
  A->>Z: POST /email {to, subject, content}
  Z->>Q: push message
  Z-->>C: 200 {success}
  Q->>M: consume
  M->>R: send
  Note over C,R: Verify: C->>Z->>A: POST /auth/otp/verify {email,code}; A checks AUTH_STORE

1.1 User Registration (Pre-requisite)

  • Admin registers users in Frappe → sync to USER_MAP KV (user:map:{email}).
  • OTP is sent only to users present in USER_MAP.

1.2 OTP Request → Email

StepActorAction
1ClientPOST /auth/otp/request (email, lang) → Zuplo Gateway
2Auth WorkerUSER_MAP check, OTP generate, AUTH_STORE.put, template load, Zuplo POST /email
3Zuplo /emailQueue or Resend direct
4Mail senderQueue consumer → Resend API

Template stored in: apps/auth-worker/src/email-otp-template.ts. Frappe does not own OTP body.

1.3 OTP Verify

  • Client POST /auth/otp/verify (email, code) → Auth Worker compares with AUTH_STORE, deletes on match, sets cookies, returns next: 'passcode/set'.

2. Zuplo Email API Callers

CallerTriggerTemplate source
Auth WorkerPOST /auth/otp/request, /auth/passcode/request-resetemail-otp-template.ts, getOtpEmailBodyHtml
Frappefrappe.sendmail → patch → send_via_zuploCaller-provided content

Shared: POST /email (Zuplo), body { to, subject, content, tenant_id? }.
Env: ZUPLO_EMAIL_API_URL, ZUPLO_EMAIL_API_KEY (Auth); mail_sender_api_url, mail_sender_api_key (Frappe).


3. Readability and Formatting

  • Issue: OTP email sentences run together; line breaks not applied.
  • Rule: Separate blocks with \n\n (BR), structure: greeting → blank → OTP request text → blank → usage → blank → OTP code (ref) → blank → sign-off.
  • Fix: Ensure OTP_BODY in email-otp-template.ts uses BR/BR2; HTML generation converts \n<br>. Avoid excess newlines; cap per block.

4. Resend Migration

  • Current: pregoi-mail-sender uses Cloudflare send_email (destination address restriction).
  • Target: Resend API (POST https://api.resend.com/emails). RESEND_API_KEY as Worker Secret.
  • Unchanged: Zuplo → Queue → pregoi-mail-sender flow; only the final send step changes to Resend.

5. Email Delivery Flows

FlowTriggerPath
A (Frappe)Frappe send_via_zuploFrappe → POST /email (Zuplo) → Queue/Resend
B (OTP/Passcode)Auth APIClient → POST /auth/otp/request → Auth Worker → POST /email → Queue/Resend

Dashboard: GET /internal/email-flow-dashboard, POST /internal/email-flow/trigger-flow-a, POST /internal/email-flow/trigger-flow-b (Bearer INTERNAL_API_KEY).


6. Email Templates — Unified Design

  • OTP: Auth Worker code (email-otp-template.ts).
  • Frappe transactional: Frappe Email Template doctype or code-based content.
  • Design: Consistent layout, minimal decoration, clear OTP block.

7. OTP Input UI

  • Requirements: Error on fail → clear 6 digits, focus first box; paste support (6 digits); visible digits (6 boxes) instead of masked dots.
  • Location: apps/client-web verify-email page, otp-digit-boxes.tsx, code-entry-form.tsx.

References


한국어

OTP 및 이메일 — 통합 기획

목적: OTP 플로우·템플릿 소유·가독성·Zuplo 호출·이메일 전달·Resend 마이그레이션·템플릿 통합·OTP 입력 UI를 한 문서에서 참조.

요약

  • §1 OTP 플로우: USER_MAP 선등록 → 클라이언트 OTP 요청 → Auth Worker(USER_MAP·AUTH_STORE)·Zuplo POST /email → Queue → Resend. 검증: POST /auth/otp/verify.
  • §2 Zuplo 호출 경로: Auth Worker(OTP·패스코드), Frappe(sendmail 패치). 공통 POST /email.
  • §3 가독성: \n\n(BR)로 문단 구분, greeting → OTP 코드 블록 → sign-off 구조.
  • §4 Resend: Cloudflare send_email → Resend API 전환. RESEND_API_KEY Worker Secret.
  • §5 이메일 플로우 A/B: Frappe 직접 vs Auth API 경유. 대시보드 /internal/email-flow-dashboard.
  • §6·§7: 템플릿 통합, OTP 입력 UI(6칸 숫자·붙여넣기·에러 시 초기화).
Help