Files
Genarrative/docs/technical/AUTH_LOGIN_OPTIONS_DESIGN_2026-04-21.md
五香丸子 46a254f142
Some checks failed
CI / verify (push) Has been cancelled
feat: add child motion entry and fix auth env
2026-05-10 18:27:51 +08:00

156 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `/api/auth/login-options` 登录方式选项设计
日期:`2026-04-21`
## 1. 文档目的
这份文档用于冻结 Rust `api-server` 首版 `GET /api/auth/login-options` 的返回 contract、配置来源与当前阶段边界确保前端在登录页读取“当前可用登录方式”时不需要依赖硬编码开关。
## 2. 当前目标
当前阶段只解决一件事:
1.`Axum` 根据服务端配置,返回当前环境启用的登录方式列表。
2. 密码登录入口由 Rust `password_entry` 固定承载,作为登录弹窗的保底入口。
本阶段明确不包含:
1. 短信或微信登录链路本身是否已经完整落地
2. 对前端返回更细粒度的 provider 配置
3. 第三方登录按钮文案、图标或 UI 布局规则
## 3. 接口 contract
### 3.1 请求
1. 方法:`GET`
2. 路径:`/api/auth/login-options`
3. 鉴权:不需要
4. 请求体:空
### 3.2 成功响应
```json
{
"availableLoginMethods": ["phone", "password", "wechat"]
}
```
字段说明:
1. `availableLoginMethods` 为字符串数组
2. 当前阶段只允许出现:
- `phone`
- `password`
- `wechat`
### 3.3 返回顺序
返回顺序固定为:
1.`phone`
2.`password`
3.`wechat`
这样可以保证前端按钮顺序稳定,不因配置解析顺序变化而漂移。
## 4. 配置来源
`api-server` 只读取以下布尔配置:
1. `SMS_AUTH_ENABLED`
2. `WECHAT_AUTH_ENABLED`
映射规则固定为:
1. `SMS_AUTH_ENABLED=true` 时返回 `phone`
2. Rust 密码登录主链可用时固定返回 `password`
3. `WECHAT_AUTH_ENABLED=true` 时返回 `wechat`
4. 短信与微信都关闭时仍返回 `["password"]`
## 5. crate 边界
### 5.1 `api-server`
负责:
1. 读取 `AppState.config`
2. 组装 `availableLoginMethods`
3. 返回项目兼容的响应 envelope
### 5.2 `module-auth`
本接口当前阶段不依赖 `module-auth`
### 5.3 前端
负责:
1. 根据 `availableLoginMethods` 决定是否展示手机号 / 微信入口
2. 不再假设某种登录方式一定存在
3.`/api/auth/login-options` 联调失败或返回空数组,前端仍保留 `password` 入口,避免登录弹窗显示“当前登录入口暂不可用”后无法继续操作。
## 6. 测试要求
至少覆盖:
1. 默认配置下返回 `["password"]`
2. 同时启用短信、密码与微信时返回 `["phone", "password", "wechat"]`
3. 前端在 `login-options` 读取失败或返回空数组时,仍展示密码登录表单
## 7. 完成定义
满足以下条件时,本任务视为完成:
1. Rust 已提供 `GET /api/auth/login-options`
2. 响应字段命名与前端约定一致
3. 配置开关可稳定映射到返回数组
4. 文档、任务清单与测试已同步更新
## 8. 2026-05-01 前端降级修复记录
本地联调时若 `api-server` 未启动或 Vite 代理暂时返回 `500``GET /api/auth/login-options` 会失败。前端必须继续遵循第 5.3 节约束:
1. `AuthGate``login-options` 读取失败时设置 `availableLoginMethods = ["password"]`
2. 该失败只代表登录方式配置探测失败,不代表登录功能不可用,因此不把 `读取登录方式失败` 写入登录弹窗错误条。
3. 登录弹窗仍展示密码登录表单,玩家可继续登录后进入创作链路。
4. 本地仍需要启动 `api-server`,否则后续 `POST /api/auth/entry` 等真实登录请求无法完成。
## 9. 2026-05-07 本地短信入口恢复记录
如果登录弹窗里短信登录页签“像是被删了”,先不要改前端表单,优先检查本地登录方式探测结果:
1. 仓库根目录 `.env.local` 里必须显式保留 `SMS_AUTH_ENABLED=true`
2. 本地启动请优先使用 `npm run api-server``npm run dev:rust``npm run dev`这些脚本会按“shell 环境优先、`.env.local` 覆盖 `.env`”合并配置。
3.`GET /api/auth/login-options` 只返回 `["password"]`,说明短信入口没有被服务端配置打开,前端只是按 contract 正常降级。
4.`SMS_AUTH_ENABLED=true` 生效时,`GET /api/auth/login-options` 至少应返回 `["phone", "password"]`,短信登录页签才会重新出现。
## 10. 2026-05-07 前端代理端口错配修复记录
如果 Rust API 直连返回 `["phone", "password"]`,但从前端域名请求 `GET /api/auth/login-options` 返回 `500`,短信页签同样会消失。此时不是登录 UI 被删除,而是 `AuthGate` 按第 5.3 节降级成 `["password"]`
本地排查顺序固定为:
1. 先请求 `http://127.0.0.1:3000/api/auth/login-options`,确认前端代理是否成功返回 JSON。
2. 再请求当前 Rust API 目标,例如 `http://127.0.0.1:3100/api/auth/login-options``http://127.0.0.1:8082/api/auth/login-options`
3. 若直连 API 成功而 3000 返回 `500`,检查 `RUST_SERVER_TARGET``GENARRATIVE_API_TARGET``GENARRATIVE_RUNTIME_SERVER_TARGET` 是否指向仍在监听的 API 端口。
4. `npm run dev` / `npm run dev:rust` 完整栈默认由脚本计算 API 端口;加载 `.env.local` 给后端使用后,脚本必须重新固定 `RUST_SERVER_TARGET`,避免 `.env.local` 中的旧代理目标覆盖本次启动的实际 API 端口。
5. `npm run dev:web` 只启动前端,不会自动拉起 Rust API如果 `.env.local` / 当前环境已经显式声明 `GENARRATIVE_RUNTIME_SERVER_TARGET``RUST_SERVER_TARGET``GENARRATIVE_API_TARGET``GENARRATIVE_API_PORT`,脚本必须固定使用该目标。目标当下不可用时只打印警告,不自动切到另一个端口,避免前端进程长时间绑定到随后会停掉的临时 API。
6. 如果 `3000` 仍然返回 `500`,先确认浏览器是不是还开着旧的前端进程。当前脚本如果因为端口占用漂移到 `3001` / `3002`,应直接关掉旧进程后重启,而不是继续用旧的 3000 页面判断登录入口状态。
## 11. 2026-05-10 `npm run api-server` 环境加载与短信 provider 排查记录
本地单独启动 `api-server` 时,环境变量合并顺序固定为:
```text
外层 shell > .env > .env.local > .env.secrets.local
```
这保证 `.env.local` 能覆盖 `.env.example` 派生出的默认值,`.env.secrets.local` 能继续覆盖本地私密密钥配置。`scripts/api-server-dev.mjs` 不得让 `.env` 后加载并覆盖 `.env.local`,否则 `SMS_AUTH_ENABLED``SMS_AUTH_PROVIDER` 可能被压回错误值。
排查“点击获取验证码但手机收不到短信”时,除了确认 `availableLoginMethods` 包含 `phone`,还必须确认当前进程实际使用的 provider
1. `SMS_AUTH_PROVIDER="mock"` 只用于本地 UI / 账号链路联调,不会向手机发送真实短信;此时应使用 `SMS_AUTH_MOCK_VERIFY_CODE`,默认 `123456`
2. 真实短信链路必须使用 `SMS_AUTH_PROVIDER="aliyun"`,并在修改 `.env.local` 后重启 `api-server`,运行中的进程不会自动切换 provider。
3. 真实 provider 是否被使用,以 `api-server` 日志中的 `provider=aliyun``provider_request_id``provider_out_id` 为准。