Skip to content

fix(dashboard): Web 详情未登录时支持一键登录 - #720

Open
47seek wants to merge 1 commit into
deepcoldy:masterfrom
47seek:feat/dashboard-one-click-login
Open

fix(dashboard): Web 详情未登录时支持一键登录#720
47seek wants to merge 1 commit into
deepcoldy:masterfrom
47seek:feat/dashboard-one-click-login

Conversation

@47seek

@47seek 47seek commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

背景

Workflow 卡片的「Web 详情(需登录)」会打开 token-free Dashboard 深链。匿名用户能加载 SPA,但管理 API 返回 401,现有弹层只能提示运行 botmux dashboard,无法在页面内完成登录。

改动

  • 保留 Workflow 卡片原有 multi_url、文案和 action;不修改「打开 Web 终端」链路。
  • Dashboard 401 在远程访问开启且机器已绑定平台时,附加 token-free X-Botmux-Login-Url,并设置 Cache-Control: no-store
  • 复用现有未登录弹层,增加「一键登录」按钮;点击后走平台 /open/<machineId> owner 登录,并只把当前 SPA hash 写入 next,登录后回到原 Workflow 路由。
  • 未绑定平台或关闭远程访问时,保持原 botmux dashboard 授权链接提示。

安全边界

  • 不开放任何 Dashboard / v3 Workflow API,原 401 权限门保持不变。
  • 响应和页面均不包含 Dashboard token 或 machine token。
  • 平台地址只接受 HTTP(S) 且拒绝带 userinfo 的 URL;machine ID 作为 path segment 编码。
  • 前端只保留 location.hash,不会把可能含 ?t=location.search 转发给平台。
  • 最终权限仍由平台现有 machine owner gate 判定;无权限用户不会获得 Dashboard 登录态。

验证

  • pnpm vitest run test/dashboard-url.test.ts test/dashboard-auth.test.ts test/dashboard-login-ui.test.ts test/v3-progress-card.test.ts test/v3-gate-card.test.ts test/v3-blocked-card.test.ts test/v3-loop-grant-card.test.ts test/v3-revisit-grant-card.test.ts(140 passed)
  • Web 终端与卡片补充回归(52 passed)
  • pnpm build
  • pnpm test:12,329 passed;codex-app-threads 的既有超时用例在全量负载下偶发失败,单文件重跑 11/11 passed
  • 本机匿名 API 实测返回 401 + token-free 登录 header;Playwright 实测弹层按钮精确保留 Workflow hash,点击进入飞书 OAuth

@47seek
47seek requested a review from deepcoldy as a code owner August 3, 2026 16:20

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex 复审结论

先不 approve,等 @deepcoldy / 申晗确认下面 F1 的产品口径;本轮没有执行合并。

F1(P2,已确认:不存在隐藏的平台改写链)

Claude2 的入口链判断正确。五类 v3 卡片默认详情 URL 都直接拼:

http://${config.dashboard.externalHost}:${config.dashboard.port}/#/v3/<runId>

其中 progress 由 daemon.ts 调用 buildV3ProgressCard(view, ...),gate / blocked / loop-grant / revisit 也都没有传 webDetailUrl override;Lark 的 send / reply / patch 出口只做 callback marker,不会改写 multi_url。因此它们不会像 buildDashboardUrls / buildTerminalUrl 那样,在「远程访问开启 + 已绑定平台」时切到 https://m-<machineId>.<platform>,也同样不会采用 BOTMUX_PUBLIC_URL

这意味着:若目标是“远程用户从 Workflow 卡片的 Web 详情按钮直接进入并一键登录”,当前改动还没有打通入口。用户先落到 LAN host:port,外网不可达时 SPA、401 header 和登录弹层都不会被加载。

请确认二选一:

  1. 本 PR 只解决已经位于平台 machine origin 的 SPA 登录态失效/匿名访问恢复:实现是完整的,但标题/背景里“Workflow 卡片入口”的口径需要收窄,明确不解决卡片深链的公网可达性。
  2. 本 PR 要解决远程用户点击 Workflow 卡片的一键登录:建议把五类卡片的默认详情 URL 收敛到共享的 dashboard public-base 生成逻辑(平台 base > BOTMUX_PUBLIC_URL > 本地 base),或由 daemon 统一注入 webDetailUrl,并补远程开/关、已绑定/未绑定的卡片测试。

F2(P3,行为面扩大但逻辑自洽)

顶层 deny401 现在只要远程访问已绑定就都会带登录 header;前端 loginUrl || (...) 因此也会让写请求、publicReadOnly 模式下的受保护请求进入登录弹层。这个范围确实比 Workflow 详情更大,但对“只读访客触发写操作时直接登录”是有用行为。我没有看到安全绕过:权限门仍在服务端,只是 401 的展示方式改变。建议作者/owner 明确确认这是预期即可,不作为阻塞项。

SSO / 编码边界复核

未发现开放重定向、XSS 或凭证泄漏:

  • 服务端和前端都只接受 HTTP(S),拒绝 URL userinfo;
  • machineId 作为 path segment 编码,machineToken 从未进入 URL;
  • next 只取 location.hash,要求 #/ 前缀、长度不超过 4096、无 C0/DEL 控制字符;
  • URL + searchParams.set 会对 #//evil.com、反斜杠、百分号和引号等重新编码,最终仍是 / 路径下的 fragment,不会把跳转 origin 改成攻击者域名;
  • 无登录 header / 非法 header 时保持旧提示。

独立验证:

  • pnpm vitest run test/dashboard-url.test.ts test/dashboard-auth.test.ts test/dashboard-login-ui.test.ts test/dashboard-endpoint.test.ts test/v3-runs-api.test.ts test/v3-progress-card.test.ts test/v3-gate-card.test.ts test/v3-blocked-card.test.ts test/v3-loop-grant-card.test.ts test/v3-revisit-grant-card.test.ts172 passed
  • pnpm build通过
  • CI buildsuccess

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants