后端在玩家还没完成强制引导(邮箱验证或 passkey 注册)时,对受保护的操作返回 403 带 code: "setup_required"。前端不看这个 code,一律按通用 403 处理,弹出"无权执行此操作"。
403
code: "setup_required"
玩家看到的是一句权限错误,而实际情况是"你还差一步没做完,去做了就能用"。没有任何东西把人引到 /setup。这一条最容易被误读成后端授权写错了 —— 它不是。
/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:
panel/src/lib/api.ts:592
if (err.status === 403) return t("forbidden");
同一个文件 :538 处的 switch (err.code) 说明按 code 分派的模式在这个代码库里已经存在,只是没用在这条路径上。
:538
switch (err.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 了,缺的只是从错误路径进去的那一跳。
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。
panel/
help wanted
有一个看着很顺手但是错的修法:给后端的 requireOnboarded 加 && p.IsAdmin(),让普通玩家绕过这个门。那等于把强制引导对所有玩家关掉,而强制引导正是这个设计要的东西。后端的判定是对的,要改的是前端怎么呈现它。
&& p.IsAdmin()
已修并真机闭环(43699b4):api.ts 对 403 setup_required 发 felis:setup-required window 事件,App Shell(Router 内)监听即跳 /setup;其余 403 完全不受影响(单测锚定:命中且仅命中该 code)。
43699b4
api.ts
403 setup_required
felis:setup-required
真机:铸一个未完成引导的会话 → CDP 打开 /submissions → 页面调用 /me/submissions 收到 403 setup_required → 自动跳 /setup 并渲染「初始化你的账户」向导(截图与网络事件序列留档)。后端判定未动。
/submissions
/me/submissions
setup_required
No dependencies set.
The note is not visible to the blocked user.
问题
后端在玩家还没完成强制引导(邮箱验证或 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:同一个文件
: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(),让普通玩家绕过这个门。那等于把强制引导对所有玩家关掉,而强制引导正是这个设计要的东西。后端的判定是对的,要改的是前端怎么呈现它。已修并真机闭环(
43699b4):api.ts对403 setup_required发felis:setup-requiredwindow 事件,App Shell(Router 内)监听即跳/setup;其余 403 完全不受影响(单测锚定:命中且仅命中该 code)。真机:铸一个未完成引导的会话 → CDP 打开
/submissions→ 页面调用/me/submissions收到 403setup_required→ 自动跳/setup并渲染「初始化你的账户」向导(截图与网络事件序列留档)。后端判定未动。