feat: deprecate email, pre-verify users + documentation
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Phone-first Auth Hardening
|
||||
|
||||
This ExecPlan is a living document. It stays synchronized with `docs/PLANS.md` (see the "Queued Next Review Focus" section there) and tracks everything needed to bring the authentication API to a consolidated, phone-first contract with a pre-verified lifecycle and consistent display paths. The remaining work must be test-driven: one sub-flow defines specs/tests, another implements against those specs, and every commit must pass the relevant backend suite.
|
||||
|
||||
## Purpose / Big Picture
|
||||
|
||||
Users must be able to log in via phone OTP without a password, the backend must keep phone numbers as the canonical identifier, and every surface that mentions a person should fall back to the phone number when email is absent. The new contract documents the public login/auth endpoints and ensures that the pre-verification lifecycle is deterministic, rate limits stay sensible, and audits display clear phone-first names. The deliverables include updated documentation, new guards/tests against regressions, and polished serializers/models that no longer assume `user.email` exists.
|
||||
|
||||
## Milestones
|
||||
|
||||
1. Spec & Test Subagent: Formalize and implement the missing specs around pre-verification, OTP purpose safety, rate-limit exposure, and display fallbacks. This milestone produces new pytest modules covering the pre-verification promise, the OTP contract (auth vs verify), and the fallback names used across staff, availability, and reviews. Success is measured by the new tests failing before implementation changes and passing afterward.
|
||||
2. Implementation Subagent: Update serializers, models, and docs to satisfy the specs. This includes reinforcing the user lifecycle (pre-verify), documenting the intended login surface (phone OTP as source-of-truth, register/token deprecated), tuning rate-limit metadata in responses, and ensuring every display path prefers phone numbers. Implementation is validated by rerunning the pytest suite (`python3 -m pytest backend/apps/accounts/tests backend/apps/salons/tests`).
|
||||
|
||||
## Progress
|
||||
|
||||
- [x] (2026-03-14 12:00 UTC) Capture the auth gaps in a dedicated ExecPlan and outline the test-first flow for the missing invariants.
|
||||
- [x] (2026-03-14 13:55 UTC) Added specs/tests for display-name fallbacks, phone auth 404 handling, and serializer coverage so the new contract fails before implementation.
|
||||
- [x] (2026-03-14 14:30 UTC) Implemented `User.display_name`, updated serializers/models/admin, documented the canonical phone OTP surfaces, and confirmed the specs pass via `python3 -m pytest backend/apps/accounts/tests backend/apps/salons/tests`.
|
||||
|
||||
## Surprises & Discoveries
|
||||
|
||||
- Pytest reports `jwt.api_jwt.InsecureKeyLengthWarning` because the test signing key is 8 bytes long.
|
||||
Evidence: the two warnings emitted during `python3 -m pytest backend/apps/accounts/tests backend/apps/salons/tests` (see the console output).
|
||||
|
||||
## Decision Log
|
||||
|
||||
- (2026-03-14 12:00 UTC) Committed to the pre-verified user lifecycle: `PhoneAuthRequestView` creates the user (if missing) before sending an auth OTP, and `PhoneAuthVerifyView` marks `is_phone_verified` true immediately upon successful verification.
|
||||
- (2026-03-14 12:00 UTC) Deferred OAuth linking and non-KSA normalization until after the current auth reliability milestone, per the user request.
|
||||
- (2026-03-14 14:05 UTC) Added `User.display_name` so every read path has a phone-first fallback and reused it in serializers/models to keep staff/review/booking strings readable for phone-only accounts.
|
||||
- (2026-03-14 14:07 UTC) Reordered the Django admin list and add forms to highlight `phone_number` so admin workflows no longer depend on email-centric defaults.
|
||||
|
||||
## Outcomes & Retrospective
|
||||
|
||||
- Phone-first auth now pre-creates customers before OTP sends, marks them verified on `/api/auth/phone/verify/`, and treats passwords as deprecated. Serializers and models no longer fall back to `user.email`; they use `User.display_name` so phone-only accounts always show a meaningful label. Django admin and README/risks docs document the canonical login surface, and the targeted pytest bundle passes with the existing JWT warnings noted above.
|
||||
+2
-3
@@ -10,12 +10,11 @@ This file tracks known gaps and risks to address in future iterations.
|
||||
- `USERNAME_FIELD` is now `"phone_number"`; `REQUIRED_FIELDS = []`; `create_superuser` accepts `phone_number`. Admin and `createsuperuser` work correctly for phone-only users.
|
||||
- Password token obtain endpoint (`/api/auth/token/`) is deprecated (`410 Gone`); phone OTP flow is the login source of truth.
|
||||
- OTP purpose isolation is enforced at verification endpoint boundaries (`/otp/verify` accepts only `verify`, `/phone/verify` accepts only `auth`).
|
||||
- Django admin user configuration remains email-centric (ordering/add form defaults), increasing operational friction for phone-only accounts.
|
||||
- Multiple serializers/model `__str__` paths in non-auth apps still fallback to `user.email`; phone-only users may get poor display/audit clarity.
|
||||
- Django admin user configuration now orders by `phone_number` and requests it on add forms to reduce friction for phone-only accounts.
|
||||
- Phone auth request now creates the customer record before issuing OTPs and marks `is_phone_verified` once `/api/auth/phone/verify/` succeeds, so phone numbers remain first-class during onboarding.
|
||||
|
||||
## Next Auth Review Points
|
||||
- DB-level guardrails for `accounts_user.phone_number` are now enforced (`NOT NULL`, `UNIQUE`, E.164 check constraint).
|
||||
- Decide user lifecycle for phone auth (create user before OTP verify vs provisional/pre-user state).
|
||||
- Abuse-control implementation for `/api/auth/phone/request/` is in place (IP throttling + persisted device signal); next step is monitor false positives and tune limits.
|
||||
- Define OAuth account-linking policy (phone/email conflicts, merge rules, trust source).
|
||||
- Add explicit tests for remaining phone-first invariants (verified-phone guards and any legacy-path regressions).
|
||||
|
||||
Reference in New Issue
Block a user