Redirect to /setup when the API returns a setup_required 403 #8

Closed
opened 2026-07-28 12:21:17 +09:00 by FLYEMOJ1 · 1 comment
FLYEMOJ1 commented 2026-07-28 12:21:17 +09:00 (Migrated from github.com)

问题

后端在玩家还没完成强制引导(邮箱验证或 passkey 注册)时,对受保护的操作返回 403 带 code: "setup_required"。前端不看这个 code,一律按通用 403 处理,弹出"无权执行此操作"。

玩家看到的是一句权限错误,而实际情况是"你还差一步没做完,去做了就能用"。没有任何东西把人引到 /setup。这一条最容易被误读成后端授权写错了 —— 它不是。

证据

Identified by Claude Opus 5 (claude-opus-5) while tracing the "认领后你无权执行此操作" report to its origin on 2026-07-28.

panel/src/lib/api.ts:592:

if (err.status === 403) return t("forbidden");

同一个文件 :538 处的 switch (err.code) 说明按 code 分派的模式在这个代码库里已经存在,只是没用在这条路径上。

后端一侧是对的,不要改:internal/api/api.go:612-621 的 requireOnboarded 只在 p.ViaSession && !p.EmailVerified && len(creds) == 0 时拒绝,返回的正是 newError(http.StatusForbidden, "setup_required", ...)。Setup.tsx:91 也已经在消费 state.setup_required 了,缺的只是从错误路径进去的那一跳。

验收

一个未完成引导的玩家触发受保护操作时,被送到 /setup 而不是看到权限错误文案。

备注

这是纯前端改动。 我不碰 panel/,所以挂 help wanted。

有一个看着很顺手但是错的修法:给后端的 requireOnboarded 加 && p.IsAdmin(),让普通玩家绕过这个门。那等于把强制引导对所有玩家关掉,而强制引导正是这个设计要的东西。后端的判定是对的,要改的是前端怎么呈现它。

## 问题 后端在玩家还没完成强制引导(邮箱验证或 passkey 注册)时,对受保护的操作返回 `403` 带 `code: "setup_required"`。前端不看这个 code,一律按通用 403 处理,弹出"无权执行此操作"。 玩家看到的是一句权限错误,而实际情况是"你还差一步没做完,去做了就能用"。没有任何东西把人引到 `/setup`。这一条最容易被误读成后端授权写错了 —— 它不是。 ## 证据 Identified by Claude Opus 5 (claude-opus-5) while tracing the "认领后你无权执行此操作" report to its origin on 2026-07-28. `panel/src/lib/api.ts:592`: ```ts if (err.status === 403) return t("forbidden"); ``` 同一个文件 `:538` 处的 `switch (err.code)` 说明按 code 分派的模式在这个代码库里已经存在,只是没用在这条路径上。 后端一侧是对的,不要改:`internal/api/api.go:612-621` 的 `requireOnboarded` 只在 `p.ViaSession && !p.EmailVerified && len(creds) == 0` 时拒绝,返回的正是 `newError(http.StatusForbidden, "setup_required", ...)`。`Setup.tsx:91` 也已经在消费 `state.setup_required` 了,缺的只是从错误路径进去的那一跳。 ## 验收 一个未完成引导的玩家触发受保护操作时,被送到 `/setup` 而不是看到权限错误文案。 ## 备注 **这是纯前端改动。** 我不碰 `panel/`,所以挂 `help wanted`。 有一个看着很顺手但是错的修法:给后端的 `requireOnboarded` 加 `&& p.IsAdmin()`,让普通玩家绕过这个门。那等于把强制引导对所有玩家关掉,而强制引导正是这个设计要的东西。后端的判定是对的,要改的是前端怎么呈现它。
Lemon-miaow commented 2026-09-24 12:02:33 +09:00 (Migrated from github.com)

已修并真机闭环(43699b4):api.ts 对 403 setup_required 发 felis:setup-required window 事件,App Shell(Router 内)监听即跳 /setup;其余 403 完全不受影响(单测锚定:命中且仅命中该 code)。

真机:铸一个未完成引导的会话 → CDP 打开 /submissions → 页面调用 /me/submissions 收到 403 setup_required → 自动跳 /setup 并渲染「初始化你的账户」向导(截图与网络事件序列留档)。后端判定未动。

已修并真机闭环(`43699b4`):`api.ts` 对 `403 setup_required` 发 `felis:setup-required` window 事件,App Shell(Router 内)监听即跳 `/setup`;其余 403 完全不受影响(单测锚定:命中且仅命中该 code)。 真机:铸一个未完成引导的会话 → CDP 打开 `/submissions` → 页面调用 `/me/submissions` 收到 403 `setup_required` → 自动跳 `/setup` 并渲染「初始化你的账户」向导(截图与网络事件序列留档)。后端判定未动。
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: FelisMC/Felis#8