06.07 — OTP coordination flow + deliberate imprecision#
The backend’s reason to exist: let N parallel Ocarina workers retrieve the right OTP for their user, even when several OTPs are generated.
Flow#
┌───────────────────────────────────────────────────────────────────┐
│ Worker (among --workers 3 of Ocarina) │
└───────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ Selenium opens the Dashboard login page │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ Acquire the distributed Redis lock (OTP_SEND_LOCK_KEY) │
│ → only this worker can click "Send OTP" during ACQ │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ min_utc_date = datetime.now(UTC) │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ L1 cache: record min_utc_date + username in the cache │
│ (keys reserved by reserve_free_cache_key) │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ Selenium types username + password + ticks OTP + click "REQ OTP" │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ IGORISTAN UI: fetch /api/otp?_user=<username> │
│ (x-api-key typed by Selenium into the UI) │
└─────────────────────────────────┬─────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ TESTS-WORKERS /api/otp: │
│ generate(secret) → otpCode │
│ createdAt = floor(now/1000)*1000 ← ms stripped │
│ event = { _user, otpCode, createdAt, expiresAt, ... } │
│ redis.set("otp:<now>:<uuid>", JSON, EX 360) │
│ return event │
└──────────────────────────────────┬────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ IGORISTAN UI: displays OTP screen │
└──────────────────────────────────┬────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ Release the OTP_SEND_LOCK_KEY Redis lock │
└──────────────────────────────────┬────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ Selenium: retrieve_dashboard_otp_code(min_utc_date, _user) │
│ ↓ │
│ GET /api/otp-history (x-api-key = IGOR_API_KEY) │
│ ↓ │
│ TESTS-WORKERS: SCAN otp:* + MGET → all events │
│ ↓ │
│ client-side filter by _user │
│ filter createdAt >= min_utc_date - 1s │
│ sort ASC by createdAt │
│ return first.otpCode │
└──────────────────────────────────┬────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────┐
│ Selenium types the OTP into the Igoristan UI │
│ → AUTHENTICATED_WITH_MFA │
└───────────────────────────────────────────────────────────────────┘
Race conditions#
- Worker A:
min_utc_date_A = 13:27:53.123, generates OTP_A at 13:27:53.250. - Worker B:
min_utc_date_B = 13:27:53.130, generates OTP_B at 13:27:53.470.
Without coordination, A could pick up OTP_B instead of OTP_A — the timestamps are close and truncated to the second.