---
id: FEAT-001
title: register
domain: auth
status: done
since_version: 0.1.0
---

# FEAT-001 — 手机号注册

## User Story

As a **未注册用户**, I want to **用手机号收验证码注册**, so that **我能建立身份开始查匹配 / 发信**。

## Acceptance Criteria

- [x] `xq register <11 位手机号>` 命令能触发 SMS 验证码下发
- [x] 返回 `request_id`（ULID）给用户，用于下一步 verify
- [x] 60 秒内同一手机号重复 register **复用原 request_id**（防刷 + 成本控制）
- [x] 手机号在服务端 **HMAC-SHA256 hash** 存储，明文不落库
- [x] 验证码有效期 5 分钟
- [x] 非法手机号格式 → 400 `invalid_phone`
- [x] SMS provider `mock`（默认）/ `aliyun`（epsilon 生产）二选一，走 env `XIANGQIN_SMS_PROVIDER`

## Tests

- `test/test_auth.py::test_register_happy_path`
- `test/test_auth.py::test_register_rate_limit`（60s 防刷）
- `test/test_auth.py::test_register_invalid_phone`
- `test/test_sms.py::test_mock_provider`
- `test/test_app.py::test_register_api_contract`

## CLI / API

- CLI: `xq register <phone>`（实现：`src/xiangqin/cli.py::cmd_register`）
- API: `POST /auth/register`（实现：`src/xiangqin/app.py::register` → `src/xiangqin/auth.py::register`）

## 依赖 / 被依赖

- **依赖**：`FEAT-027 health`、SMS provider（`src/xiangqin/sms/`）
- **被依赖**：`FEAT-002 verify`（必须 request_id 才能 verify）、所有需要 session 的功能

## 风险 / 边界

- **不做**：邮箱注册 / OAuth —— 相亲场景手机号是合规必需
- **待做**：`#009 实名认证` 在注册后强制，未通过不给查 / 不给发信
- **隐私红线**：手机号永远不落明文（`PHONE_SALT` 从 env 注入，epsilon 独立 salt）

## 相关

- issue #002 / #003（salt 修复）
- scenarios `day-in-life-first-envelope-user.md`（注册是第 1 步，待写）
