feat(auth): switch signup to OTP verification flow

Replace legacy signup with start/verify/resend endpoints, add OTP-focused mail templates and auth rate limits, and align compose/env/runbook for local self-hosted Supabase OTP behavior.
This commit is contained in:
qzl
2026-02-25 13:34:02 +08:00
parent 02e5e52e1f
commit 1cc8fa1abf
16 changed files with 707 additions and 112 deletions
@@ -0,0 +1,85 @@
# Auth Signup OTP Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 将注册流程改为两阶段 OTPstart/verify/resend),并移除旧 `/auth/signup` 路由。
**Architecture:** 后端继续作为 Supabase Auth 的薄封装层。`signup/start` 只创建待验证用户并触发验证码邮件;`signup/verify` 通过 `verifyOtp(type=signup)` 完成验证并返回 token`signup/resend` 负责重发验证码。保留现有 token 响应模型,最小化客户端和网关改造。
**Tech Stack:** FastAPI, Pydantic, supabase-py, pytest
---
### Task 1: 更新认证 Schema
**Files:**
- Modify: `backend/src/v1/auth/schemas.py`
- Test: `backend/tests/unit/v1/auth/test_auth_models.py`
**Step 1: Write the failing test**
-`SignupStartRequest``SignupVerifyRequest``SignupResendRequest` 增加字段校验测试。
**Step 2: Run test to verify it fails**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/unit/v1/auth/test_auth_models.py -q`
**Step 3: Write minimal implementation**
- 新增 start/verify/resend 的请求与响应模型。
**Step 4: Run test to verify it passes**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/unit/v1/auth/test_auth_models.py -q`
### Task 2: 改造 Service/Gateway 为三阶段 OTP
**Files:**
- Modify: `backend/src/v1/auth/service.py`
- Modify: `backend/src/v1/auth/gateway.py`
- Test: `backend/tests/unit/v1/auth/test_auth_service.py`
**Step 1: Write the failing test**
-`signup_start/signup_verify/signup_resend` 增加 service 转发与 gateway Supabase 调用行为测试。
**Step 2: Run test to verify it fails**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/unit/v1/auth/test_auth_service.py -q`
**Step 3: Write minimal implementation**
- 删除旧 `signup` 入口,新增三个方法。
- `signup_verify` 使用 `verify_otp` 并返回 `AuthTokenResponse`
- `signup_resend` 调用 `resend(type=signup)` 并返回通用消息。
**Step 4: Run test to verify it passes**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/unit/v1/auth/test_auth_service.py -q`
### Task 3: 替换 Router 路由并删除旧 signup
**Files:**
- Modify: `backend/src/v1/auth/router.py`
- Test: `backend/tests/integration/test_auth_routes.py`
- Test: `backend/tests/e2e/test_auth_flow.py`
**Step 1: Write the failing test**
- 集成测试改为 `/auth/signup/start``/auth/signup/verify``/auth/signup/resend`
- 删除对旧 `/auth/signup` 的断言。
**Step 2: Run test to verify it fails**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/integration/test_auth_routes.py -q`
**Step 3: Write minimal implementation**
- Router 新增三条路由并移除旧 `/signup`
- 保持 RFC7807 错误映射行为。
**Step 4: Run test to verify it passes**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/integration/test_auth_routes.py -q`
### Task 4: 全量验证
**Files:**
- Test: `backend/tests/unit/v1/auth/test_auth_models.py`
- Test: `backend/tests/unit/v1/auth/test_auth_service.py`
- Test: `backend/tests/integration/test_auth_routes.py`
- Test: `backend/tests/e2e/test_auth_flow.py`
**Step 1: Run focused suite**
- Run: `PYTHONPATH=backend/src uv run python -m pytest backend/tests/unit/v1/auth backend/tests/integration/test_auth_routes.py backend/tests/e2e/test_auth_flow.py -q`
**Step 2: Report evidence**
- 记录通过/失败数量与关键行为验证结果。
+17 -3
View File
@@ -102,7 +102,6 @@ tmux kill-session -t social-dev
| 环境变量 | 说明 | 默认值 | 有效范围 |
|----------|------|--------|----------|
| `SOCIAL_WEB__SERVER` | Web 服务器类型 | gunicorn | uvicorn/gunicorn |
| `SOCIAL_WEB__HOST` | 监听地址 | 0.0.0.0 | - |
| `SOCIAL_WEB__PORT` | 监听端口 | 8000 | 1-65535 |
| `SOCIAL_WEB__RELOAD` | 开发模式热重载 | false | true/false |
@@ -143,11 +142,24 @@ docker compose --env-file .env -f infra/docker/docker-compose.yml --profile job
## Auth/Profile 验证
```bash
# signup: username + email + password
curl -sS -X POST http://127.0.0.1:8000/api/v1/auth/signup \
# 注意:默认模板地址 http://mail-templates/* 仅在 Docker Compose 内网可用。
# 生产环境请替换为 gotrue 可访问的模板 URL。
# signup start: username + email + password(发送验证码)
curl -sS -X POST http://127.0.0.1:8000/api/v1/auth/signup/start \
-H 'Content-Type: application/json' \
-d '{"username":"demo","email":"demo@example.com","password":"secret123"}'
# signup verify: email + token6位验证码)
curl -sS -X POST http://127.0.0.1:8000/api/v1/auth/signup/verify \
-H 'Content-Type: application/json' \
-d '{"email":"demo@example.com","token":"123456"}'
# signup resend: email(重发验证码)
curl -sS -X POST http://127.0.0.1:8000/api/v1/auth/signup/resend \
-H 'Content-Type: application/json' \
-d '{"email":"demo@example.com"}'
# login: email + password
curl -sS -X POST http://127.0.0.1:8000/api/v1/auth/login \
-H 'Content-Type: application/json' \
@@ -174,3 +186,5 @@ curl -sS -X PATCH http://127.0.0.1:8000/api/v1/profile/me \
| 2026-02-24 | 开发阶段 compose 暂不编排 web/worker,仅保留 redis/supabase 与 init-job |
| 2026-02-24 | 新增 dev-app-up 脚本:手动基础设施后,一键 bootstrap + tmux 拉起 web/worker |
| 2026-02-25 | 补充迁移防遗漏规则:容器迁移命令统一追加 --build;开发调试优先使用本地 CLI 一次性迁移脚本 |
| 2026-02-25 | Auth 注册切换为 OTP 三段式:signup/start、signup/verify、signup/resend;邮件模板改为纯验证码展示 |
| 2026-02-25 | 清理未使用配置类:删除 WebSettings/GunicornSettings/WorkerSettings/WorkerGroupSettings(脚本仍使用环境变量启动服务) |