SmsSender Protocol(fake/tencent)+ 验证码生命周期(哈希存储/一次性/ 5 次作废)+ 号码-IP-设备三重频控 + 掩码纪律(FR-ACC-04/14,TD-32; 真实发送待签名审核)。 实现:packages/identity/sms_login.py(SmsStore/SmsSender 双 Protocol、 FakeSmsSender 打日志、TencentSmsSender 包官方 SDK 失败映射 61000、 SmsAuthService 验证码生命周期 + UTC+8 时段桶频控);路由 POST /auth/sms/send、POST /auth/sms/verify(provider="phone" 映射 + issue_session + TokenPairResponse,与华为通道零耦合)。测试:单测 37 个 (内存 dict 实现 store、注入时钟模拟 TTL;号码规范化/掩码/频控矩阵/ 验证码四要素/腾讯通道桩测),集成 7 个(send→verify 双令牌闭环、同号 同 user、脚本化刷量 11 发第 11 次 42911、IP/设备维度、错 5 次作废)。 门禁:ruff/mypy(identity+apps/api)/lint-imports 全绿,单测 275 通过、 集成 23 通过。 偏差说明: 1. SmsSender.send_code 收 (phone, masked, code) 三参而非单一「掩码键」: 腾讯通道下发必须有真实号码(掩码/哈希无法投递);防泄漏由「实现层 不得记录 phone」约定 + structlog 全局手机号脱敏兜底。 2. 频控计数按「请求」计(含被拒请求)且在限额检查前自增:否则被拒 请求不烧额度,攻击者可无限试探;同时这是「连发 11 次第 11 次 42911」脚本化验收在真实时钟下成立的前提。 3. request_code 对 sender 逃逸的非 AppError 异常兜底包成 61000: 通道故障不得以 5xxxx 内部错误形式稀释告警(TencentSmsSender 自身 映射为主,此处仅接漏网)。 4. wire 请求模型(SmsSendRequest/SmsVerifyRequest)定义在 sms_login.py 内(任务文档允许的两选一,未新建 sms_schemas.py)。
packages/identity/ — 账号与会话
职责(架构 §4.1):账号、登录、会话、设备、游客迁移、同意授权记录。
不负责:权益判定(归 billing)。
铁律
identity 不得依赖任何其他业务域(架构 §4.2)—— 登录链路不能被业务拖累。
import-linter 契约 identity must not depend on any other business domain 会
在 CI 拦下违规 import。
已实现
id_user/id_user_identity/id_consent表- 外部身份 → 内部
user_id映射(内部主键与外部身份解耦,便于加登录通道) - 同意记录写入
- JWT access token(
packages/shared/security.py)
待实现
| 需求 | 内容 |
|---|---|
| FR-ACC-01 | 华为账号登录(UnionID/OpenID) |
| FR-ACC-04 | 手机号验证码登录(5 分钟有效、单号限频) |
| FR-ACC-05 | 双令牌:id_session + 服务端可撤销的 refresh token |
| FR-ACC-02/03 | 游客模式与数据合并(合并必须幂等) |
| FR-ACC-08 | 人脸单独同意页(CR-01:必须独立,不得混入总协议) |
| FR-ACC-09 | 账号注销:7 日内彻底删除,含 COS 对象(CR-03) |
| FR-ACC-11 | 未成年人判定与功能限制(CR-04) |
| FR-SYS-01 | 越权防护:所有资源访问校验归属,不能只靠 ID 不可猜 |
POST /auth/dev-token 只是脚手架,DEV_AUTH_ENABLED=false 时不可用,
生产环境必须关闭。