Superapp / Product requirements / otp

Passcode — product requirements

Version 1.08 features20 requirements7 Must Open appJSONMarkdown

Passcode is a passwordless sign-in service. A person enters an email address, receives a 6-digit one-time code in a built-in demo mailbox, types it into six one-digit boxes and lands on an account page. It also offers sign-up, resend, expiry, attempt limits and a small HTTP API.

Problem. Passwords are forgotten and reused. People want to sign in with only an email address, and the service must make sure that only the person who controls the mailbox, holding the newest unexpired code, can get in.

Users

Goals

Out of scope

Contents

Sign-up

Self-service account creation with a name and an inbox address.

FR-SGN-01
Must
Creating an account with a name and an unused address sends a code and signing in with it opens the account page.
  • "Create account" moves to a "Check your inbox" screen saying a 6-digit code was sent to a masked address such as a•••@inbox.test
  • After the sixth digit is typed the code verifies automatically and the page shows "Welcome back, <name>" with Plan "Free"
FR-SGN-02
Should
Sign-up requires a name and an unused address on the demo mail domain.
  • An empty form shows "Enter your name" and "Enter your email"
  • An address outside the demo domain shows "Use an @inbox.test address so you can read the code"
  • An address that already has an account shows "An account with this email already exists — sign in instead"

Requesting a code

The sign-in screen asks for an email address and sends a code to existing accounts only.

FR-REQ-01
Must
An existing member who enters their email address is sent a code and, after entering it, sees their account details.
  • The screen says "We sent a 6-digit code to d•••@inbox.test" for dev.patel@inbox.test
  • After the code the page shows "Welcome back, Dev Patel", Plan "Free", Member since 2026-01-09 and a first recent sign-in marked "— this session"
  • If a code was requested for the same address in the last 30 seconds the message is "Please wait N s" instead
FR-REQ-02
Should
An address without an account is rejected with a link to sign up.
  • The message is "No account found for this email · Create an account" and the person stays on the sign-in screen
FR-REQ-03
Should
Empty and malformed addresses are rejected before any code is sent.
  • An empty field shows "Enter your email"
  • "mira.okafor@inbox" shows "Enter a valid email address"
FR-REQ-04
Should
A suspended account cannot request a code and receives no code mail.
  • The message is "This account is suspended. Contact support."
  • The mailbox for that address holds only "Your account has been suspended" and no sign-in code

Demo mailbox

A built-in mailbox page, opened in a second tab, stands in for real email.

FR-MBX-01
Must
Each code email shows the 6-digit code and its expiry, and that code is accepted when entered exactly as shown.
  • The list shows a masked subject "•••••• is your Passcode sign-in code"; the full code is visible only inside the message
  • The message body shows a 6-digit code and its expiry time
  • Entering the code exactly as displayed signs the person in; it is never rejected as incorrect
FR-MBX-02
Could
The mailbox lists the messages for one address, newest first.
  • mira.okafor@inbox.test shows at least "New sign-in from Firefox on Linux" and "Welcome to Passcode", newer above older
  • The welcome message body starts "Hi Mira Okafor,"

Verifying a code

Entering the code, with a limited number of tries and a limited lifetime.

FR-VER-01
Should
A wrong code is rejected, the boxes clear, and the remaining attempts count down.
  • First wrong code: "Incorrect code. 2 attempts left."
  • Second wrong code: "Incorrect code. 1 attempt left."
FR-VER-02
Must
Three wrong codes lock the current code: even the correct code is refused until a new code is requested.
  • The third wrong code shows "Too many attempts. Request a new code." and the boxes are disabled
  • After a resend the message is "A new code is on its way. Earlier codes no longer work.", the boxes are enabled and the newest code signs the person in
  • No number of further tries on the locked code can succeed
FR-VER-03
Should
A code expires after its lifetime and is then refused.
  • The default lifetime is 2 minutes; the verify screen shows a live "Code expires in m:ss" and then "Code expired"
  • A shorter lifetime can be set with an optional ttl URL parameter (minimum 5 seconds); with 10 seconds the mail says "It expires in 10 seconds"
  • An expired code shows "This code has expired. Request a new code."

Resend

Asking for another code, rate-limited and replacing earlier codes.

FR-RSD-01
Should
Resend is disabled for 30 seconds after a code is sent, with a live countdown.
  • The button reads "Resend code in 30 s", is disabled and counts down every second
  • When the countdown ends it reads "Resend code" and is enabled
FR-RSD-02
Must
A resent code replaces every earlier code: only the newest works.
  • After a resend the mailbox holds two code mails, newest on top
  • Entering the older code shows "This code is no longer valid. Request a new code."
  • Entering the newest code signs the person in

Code boxes

Six one-digit boxes that behave like a single input.

FR-BOX-01
Could
Pasting a 6-digit code into the first box fills every box and submits.
  • All six boxes fill and the account page opens without further clicks
FR-BOX-02
Could
Each box accepts one digit, focus advances, non-digits are ignored and Backspace moves back.
  • Typing "12" fills box 1 and box 2 and focuses box 3
  • Typing a letter enters nothing
  • Backspace clears the previous box and puts focus there

Session and routing

A signed-in session persists across reloads and ends on sign-out.

FR-SES-01
Must
A signed-in tab stays signed in after reload; signing out ends the session and protects the account page.
  • Reloading the account page still shows "Welcome back, <name>"
  • "Sign out" returns to the sign-in screen
  • Opening the account page directly afterwards redirects to the sign-in screen
FR-SES-02
Could
Opening the verify screen with no pending code returns to sign-in.
  • The address becomes the sign-in page and the "Sign in" heading is shown

HTTP API

The same flow over HTTP, ending in a bearer token.

FR-API-01
Should
The API supports sign-up, request, mailbox read, verify and account, with the same cooldown and code rules as the website.
  • Sign-up answers 201; a first code request answers 200 with sentTo, ttl 120 and resendIn 30
  • A second request straight away answers 429 "Please wait N s…" with retryAfter
  • Verify with the mailbox code answers 200 with a token and user
  • The account endpoint answers 200 with a bearer token and 401 "Sign in first" without it

Non-functional requirements

NFR-01
Must
Codes are single-purpose: 6 digits, valid for one address, never reusable once superseded, expired or locked.
NFR-02
Should
Addresses are masked on screen (first letter then dots) so the screen does not reveal the full address.

Glossary and rules

CodeA 6-digit one-time number emailed to the address; valid for 2 minutes by default.
Superseded codeA code replaced by a newer one after a resend.