# 2026-04-02 工作记录

## Sprint 13 执行完成

**执行时间**: 2026-04-02

### 完成的修复

#### ✅ GAP-01: 角色继承 — 确认已完整实现
- `internal/service/role.go`: 循环检测 + 深度限制（5层）已实现
- `internal/api/middleware/auth.go`: 祖先权限汇总已接线
- **无需修改**

#### ✅ GAP-02 + 密码历史: SMS重置时序泄漏修复 + doResetPassword补写历史
- `internal/service/password_reset.go`:
  - SMS验证码比较改用 `crypto/subtle.ConstantTimeCompare`
  - `doResetPassword` 新增密码历史检查与记录
  - 新增 `WithPasswordHistoryRepo()` 链式注入方法
- `cmd/server/main.go`: 注入 passwordHistoryRepo 到 passwordResetService

#### ✅ GAP-05: AnomalyDetector — 确认已接线
- main.go 第111-112行已完整初始化
- **无需修改**

#### ✅ GAP-03: 设备信任链路补齐
- `internal/api/handler/auth_handler.go`: Login 补齐 device_id/name/browser/os 字段
- `internal/api/handler/sms_handler.go`: 从 stub 重写为真实实现，调用 AuthService.LoginByCode，支持设备注册
- `internal/service/auth.go`: 导出 BestEffortRegisterDevicePublic 供外部调用

### 验证结果
- ✅ go build ./... 通过
- ✅ go vet ./... 通过
- ✅ go test ./... -count=1 全部通过

### 遗留项（Sprint 14）
- 邮箱验证码登录 handler 仍是 stub（auth_handler.go::LoginByEmailCode）
- 前端 device_id 稳定化方案（当前为随机生成）
- SlidingWindowLimiter 死代码清理（R6-02）

---

## Sprint 14 执行完成（同日继续）

**执行时间**: 2026-04-02（续）

### 修复内容（彻底收口所有遗留问题）

#### ✅ 邮箱验证码登录 stub 修复
- `internal/api/handler/auth_handler.go`:
  - `SendEmailCode`：从 stub 改为调用 `authService.SendEmailLoginCode`
  - `LoginByEmailCode`：从 stub 改为调用 `authService.LoginByEmailCode`，支持设备信息注册
  - `SupportsEmailCodeLogin()`：从硬编码 `false` 改为动态检测 `authService.HasEmailCodeService()`
  - `ActivateEmail`：从 stub 改为调用 `authService.ActivateEmail`
  - `ResendActivationEmail`：从 stub 改为调用 `authService.ResendActivationEmail`（防枚举返回）
  - 删除三个永不被路由的 stub（ForgotPassword/ResetPassword/ValidateResetToken）
- `internal/service/auth_email.go`: 新增 `HasEmailCodeService()` 检测方法

#### ✅ R6-01 webhook recordDelivery context.Background 修复
- `internal/service/webhook.go`: 用 `context.WithTimeout(context.Background(), 5*time.Second)` 替换裸 `context.Background()`

#### ✅ R6-02 SlidingWindowLimiter 死代码清理
- 删除 `internal/security/ratelimit.go`（整个文件，全部类型均无外部引用）

#### ✅ 前端 device_id 稳定化
- `frontend/admin/src/pages/auth/LoginPage/LoginPage.tsx`:
  - `buildDeviceFingerprint` 改为从 localStorage 读取 `ums_device_id`
  - 不存在时用 `crypto.randomUUID()` 生成并持久化
  - 优雅降级：localStorage 不可用时退化为一次性 ID

### 验证结果（最终）
- ✅ go build ./... 通过
- ✅ go vet ./... 通过
- ✅ go test ./... -count=1 全部通过（无 FAIL）
- ✅ npm lint 通过（exitCode=0）
- ✅ npm build 通过（657ms）

### 所有遗留问题清零
- 所有已知 P2 stub handler 已修复
- 死代码已清除
- 前端设备信任链路完整闭环
