Authentication isn't about who someone is today. It's about never losing them tomorrow.
Most auth systems are built for the moment of login, not the lifetime of a human. They answer "can this person get in right now?" but ignore the harder question: "will this still be the same person in five years?"
The result is identity fragmentation. A user signs in with Google today, with SMS next year, forgets which email they used, changes their phone number, and the system quietly creates a stranger in their place. We don't lose users to bad passwords. We lose them to bad continuity.
A phone number is not a permanent identity. ~35 million phone numbers are recycled every year. A number you own today may belong to a stranger in 2-5 years.
The Rule: Every account must carry an email, even when SMS is the primary auth method. The email does not need to be a verified provider on day one - it can live as a field on the user record (a single updateUser mutation). It exists as the fallback that survives when the phone number doesn't.
Why: When a recycled number tries to sign in after a period of inactivity, the email is the thread that proves who the original human was - and blocks the stranger.
Before creating a user, ask: does this human already exist here?
The Rule: On any new auth attempt, perform a lookup by phone number (scoped to tenant/site). If a user exists, derive their external ID, resolve their providers, and offer to link instead of create.
Why: This stops "User 2." It ensures one human maps to one record per site. Instead of fragmenting identity across accounts, the system stitches the human back to themselves: "Welcome back - sign in with Google to continue."
A phone number is treated with the same strictness as an email: a unique key.
The Rule: A phone number maps to exactly one user per tenant. Changing a phone number is a deliberate re-link (unlink old, verify new), not a casual overwrite. Validate every new phone against Rule #2 before binding it.
Why: If one number can belong to multiple accounts, the Rule #2 lookup collapses - the system can no longer answer "whose account is this?" Uniqueness is the foundation the entire protocol stands on.
Auth is the pure layer. A user is not created until the provider (e.g. Firebase) has signed off - meaning the OTP is entered and the provider data actually changes. It is all-or-nothing: no half-created users from network drops or abandoned flows.
The provider answers "what is verified?" The application database keeps a record, but it never overrides the provider's truth.
- Verify: Never trust an identifier until the provider confirms ownership (OTP entered, provider added).
- Bridge: Before creating anyone, check if they already exist and link instead.
- Bind: Enforce uniqueness so every identifier points to exactly one human.
Standard auth tutorials optimize for the first login. This protocol optimizes for the fiftieth - across phone changes, provider migrations, years of inactivity, and recycled numbers. It treats identity as something to preserve, not just verify.