From d58df1b48bf1fc293652cdf137c19f72bde3054d Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Thu, 1 Oct 2026 22:29:18 +0800 Subject: [PATCH] docs(tasks): staging fixed-OTP login skips set-password (BUG-1152) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE --- docs/tasks/README.md | 1 + ...TASK-staging-otp-skip-password-20261001.md | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 docs/tasks/TASK-staging-otp-skip-password-20261001.md diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 40f6fb1e..59e7224f 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -402,3 +402,4 @@ | `TASK-consult-plain-answer-20261001.md` | `PROGRESS-consult-plain-answer-20261001.md` | 普通对话「还是废话」:09-17 四步开场形状(格局名 → 谁推谁修 → 扮演哪个象)逼出谜语,问父母时爸妈被揉成一段;产品授权推翻该形状,改成先答 + 按问题里的对象分段 + 人话自检 + 空宫不单独下结论 + 父母卡标 mother/father(BUG-1132~1134) | **已实现,待 Claude 验收**(fork 子代理直接执行);未推 staging、未部署;模型对比为环境缺口,真机清单 `docs/testing/consult-plain-answer-20261001.md` | 分支 `codex/consult-plain-answer-20261001` | | `TASK-consult-answer-clock-20261001.md` | `PROGRESS-consult-answer-clock-20261001.md` | 普通对话答题时钟 70 s 容不下推理模型(v4-pro 77 s),无出生分钟路线只受 110 s 工具钟管;产品定 5 分钟防卡死(BUG-1142) | **已实现,待 Claude 验收**(直接执行) | 分支 `codex/consult-answer-clock-20261001` | | `TASK-consult-timeline-no-plan-20261001.md` | `PROGRESS-consult-timeline-no-plan-20261001.md` | 普通对话进度栏提前打勾:回答提纲在算盘前就作为四行步骤显示并全部打勾(BUG-1145);产品选 B 去掉提纲行,只显示真实步骤 | **实现完成,待 Claude 验收**(直接执行) | 分支 `codex/consult-timeline-no-plan-20261001` | +| `TASK-staging-otp-skip-password-20261001.md` | `PROGRESS-staging-otp-skip-password-20261001.md` | staging 新邮箱用固定验证码登录后被强制设置密码,测试者误以为要密码登录;产品选「测试通道验证码登录跳过设置密码」,生产不变(BUG-1152) | **待领取** | 分支 `codex/staging-otp-skip-password-20261001` | diff --git a/docs/tasks/TASK-staging-otp-skip-password-20261001.md b/docs/tasks/TASK-staging-otp-skip-password-20261001.md new file mode 100644 index 00000000..c914dc8f --- /dev/null +++ b/docs/tasks/TASK-staging-otp-skip-password-20261001.md @@ -0,0 +1,84 @@ +# TASK · staging 固定验证码登录跳过「设置密码」(2026-10-01) + +## 基线 + +- `origin/staging` = `b62308c4`(开工时重新 `git fetch origin --prune` 核对) +- 分支 / worktree:`codex/staging-otp-skip-password-20261001` / `.worktrees/staging-otp-skip-password-20261001` +- 只改前端登录组件与测试;不动服务端、数据库、workflow、环境变量 + +## 事故实证 + +产品负责人反馈:「staging 现在要密码才能登录,不是用固定验证码吗?」 + +| 事实 | 证据 | +| --- | --- | +| staging 固定码通道仍开启 | 线上 `/login` 页 RSC 负载带 `testOtp`(6 位码,值不写进文档);对虚构邮箱调用 `POST /api/auth/email-otp/send-verification-otp` 返回 `200 {"success":true}` | +| 固定码提示从常驻变为 10 秒浮层 | `3e0c615f`(09-30,BUG-1121/1122)删除登录卡片上的 `auth-test-channel` 段落,改成点「发送验证码」后才出现的 `notifyInfo(..., TEST_OTP_NOTICE_MS)`。**本单不恢复常驻提示**(产品只选了第 2 条) | +| 新邮箱用验证码登录后被强制设置密码 | `frontend/src/components/email-otp-login.tsx` 的 `verifyOtp`:`selfHostedAuthActions.hasPassword()` 为 false 时 `setStep("set-password")`,该表单没有跳过入口。自 `ab2944f7`(07-27)起如此 | + +## 根因 + +`verifyOtp` 不区分测试通道:staging 测试者每用一个新邮箱,都会在验证码通过后被拦在「设置登录密码」。验证码校验成功时服务端会话已经建立(`set-password` 只是登录后的界面步骤,`enterApp()` 只是跳转),所以这一步在测试通道里纯属阻碍。 + +## 决策记录 + +- 产品负责人 2026-10-01 选定:**staging 用固定验证码登录新邮箱时,跳过「设置密码」直接进入应用。** +- 范围只限 `testMode`(即服务端配置了 `IDENTITY_TEST_OTP`,生产不配置,`testOtp` 为 null)。生产行为一字不变。 +- 只对「验证码登录」模式(`mode === "otp"`)生效。「注册账号」模式的说明就是「验证邮箱后设置密码」,测试者主动选它时仍走设置密码步骤。 +- 不恢复登录卡片上的常驻固定码提示(产品未选第 1 条);BUG-1121/1122 的浮层设计不变。 + +## 硬红线 + +1. 不改服务端鉴权、Better Auth 配置、`IDENTITY_TEST_OTP` 读取逻辑、`/api/account/password`。 +2. 非测试通道(`testMode` 为 false)下 `verifyOtp` 的分支顺序与行为完全不变:二步验证 → 无密码进设置密码 → 注册模式已有账户提示 → 进入应用。 +3. 测试通道下二步验证分支照常优先(有 MFA 的账号仍要第二因素)。 +4. 不新增第二套登录表单、不新增加载动画;`page.tsx` 不增长。 +5. 不在任何文件写入真实固定码以外的账号信息;文档里不写固定码的值。 + +## 任务分解 + +### T1 跳过设置密码(BUG-1152) + +`verifyOtp` 自托管分支内,`hasPassword` 为 false 时:若 `testMode && mode === "otp"` → 直接 `await enterApp()`;否则维持 `setStep("set-password")`。可以把 `hasPassword()` 调用在这种情况下省掉,也可以保留调用后判断,执行方择一并在进度记录里说明。 + +验收: +- 测试通道 + 验证码登录 + 无密码账户 → 不进入 `set-password`,调用 `enterApp`(会记录协议同意并跳转 `/`)。 +- 测试通道 + 注册模式 + 无密码 → 仍进入 `set-password`。 +- 非测试通道 + 验证码登录 + 无密码 → 仍进入 `set-password`。 +- 测试通道 + 需要二步验证 → 仍进入 `two-factor`。 + +### T2 回归测试 + +在 `frontend/tests/identity-login-provider.test.ts` 补断言覆盖 T1 的四种情形(该文件现有风格是对组件源码做正则断言;能做行为级渲染测试更好,二选一并说明)。既有断言不改;若必须改,写「原值 / 新值 / 原因」。 + +### T3 记录 + +- `docs/BUG_HISTORY.md` 新增 BUG-1152:现象「staging 新邮箱用固定验证码登录后被要求设置密码,测试者误以为必须用密码登录」,根因见上,关联 BUG-1121/1122(提示改为浮层使问题更显眼)。 +- `CHANGELOG.md` 一行:staging 测试通道验证码登录不再要求设置密码(生产不受影响),Skill 版本不 bump。 +- `docs/testing/staging-otp-skip-password-20261001.md` 真机清单:新邮箱 → 发送验证码 → 输入浮层里的固定码 → 直接进入首页;再用「注册账号」走一遍确认仍要求设置密码。 +- 本文件在 `docs/tasks/README.md` 状态板登记,合入 staging 的同一次推送里改状态。 + +## 让步顺序 + +T1 > T2 > T3。行为级渲染测试做不起来时退回源码正则断言,不得省略四种情形。 + +## 开工前置命令 + +```bash +cd /workspace/Jyotisha && git status -sb | head -1 +git fetch origin --prune +git worktree add -b codex/staging-otp-skip-password-20261001 .worktrees/staging-otp-skip-password-20261001 origin/staging +cd .worktrees/staging-otp-skip-password-20261001/frontend && npm ci +./node_modules/.bin/tsc --noEmit && npm run lint && node --test tests/identity-login-provider.test.ts # 记录基线 +grep -oE "^## BUG-[0-9]+" ../docs/BUG_HISTORY.md | sort -t- -k2 -n | tail -1 # 应为 BUG-1151;若已被占用顺延 +``` + +## 验收口径 + +- `tsc --noEmit` 0 错;`npm run lint` 0 error;`identity-*` 测试全过,前端测试总数不低于基线。 +- `next build` 后 `/` 仍 Static;首屏 gzip ±2%(登录页不在首屏,预期不变)。 +- 部署后 staging `/api/health` 的 `deployment.gitCommit` 等于实现提交;真机按 `docs/testing/` 清单由产品负责人走查(Claude 无登录态时记为环境缺口)。 + +## BUG 编号起点 + +BUG-1152(开工时核对 `docs/BUG_HISTORY.md` 最大号)。