Skip to content

feat: Resolve phone OTP launch-scope decision #109

Merged
3m1n3nc3 merged 1 commit into
learnault:mainfrom
simplicityf:feat/phone-otp
Jul 20, 2026
Merged

feat: Resolve phone OTP launch-scope decision #109
3m1n3nc3 merged 1 commit into
learnault:mainfrom
simplicityf:feat/phone-otp

Conversation

@simplicityf

Copy link
Copy Markdown
Contributor

Summary

  • Resolves the blocked "phone OTP scope" decision: retained for launch. Full rationale, threat model, and cost analysis recorded in docs/decisions/0001-phone-otp-authentication.md.
  • Adds POST /auth/otp/request and POST /auth/otp/verify, disambiguated by an optional Bearer token: unauthenticated = phone login (anti-enumeration, mirrors forgotPassword), authenticated = verify/attach a phone number to your own account.
  • New OtpChallenge Prisma model (hashed code, expiry, attempts/lockout, consumption) plus User.phone/phoneVerifiedAt.
  • Provider-abstracted SMS layer (SmsProvider interface + MockSmsProvider, gated by SMS_PROVIDER=mock) — swapping in a real carrier later doesn't touch the OTP service.
  • Rate limiting on all three axes: IP (otpLimiter middleware), phone (cooldown + hourly cap), and device (optional deviceId, hourly cap).
  • Refactored login()'s account-status checks (deactivated/pending-deletion/deleted) into a shared helper so OTP login enforces identical rules — existing login tests still pass unchanged.
  • Updated OpenAPI docs, docs/API.md, .env.example, and ROADMAP.md (item resolved from conditional to done).

Test plan

  • tests/otp.service.test.ts — phone normalization, hashing, expiry, attempt increment/lockout, single-use consumption
  • tests/auth.controller.test.ts — new requestOtp/verifyOtp coverage: anti-enumeration, phone-conflict on verification, phone/device rate-limit 429s, locked-challenge 429
  • Full suite: npx vitest run → 423 passed, 3 skipped (pre-existing, no local DB)
  • npx tsc --noEmit and npx eslint clean
  • Verified OpenAPI spec registers both new paths and their component schemas
  • Redacted curl walkthrough in the ADR's "Verification evidence" section

Related issue

Closes #80

Screenshot

0

… a hashed/expiring/attempt-limited challenge model behind a provider-abstracted SMS interface with phone/IP/device rate limits.
@simplicityf

Copy link
Copy Markdown
Contributor Author

@3m1n3nc3

If you are merging this PR, kindly help me look into my previous PR that you merged. I did not receive any FoxPoints on it. Thank you!

@3m1n3nc3
3m1n3nc3 merged commit 4c91f0b into learnault:main Jul 20, 2026
1 check passed
@3m1n3nc3

Copy link
Copy Markdown
Contributor

@3m1n3nc3

If you are merging this PR, kindly help me look into my previous PR that you merged. I did not receive any FoxPoints on it. Thank you!

Hi @simplicityf I think you should reach out to the GF support team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Decide and Implement Phone OTP Authentication API

2 participants