Skip to content

fix(dashboard): proxy SSH source requests and correct the dev:web README - #5270

Merged
huangruiteng merged 2 commits into
loopx-project:mainfrom
songoow:codex/dashboard-dev-proxy-and-readme
Sep 28, 2026
Merged

huangruiteng merged 2 commits into
loopx-project:mainfrom
songoow:codex/dashboard-dev-proxy-and-readme

Conversation

@songoow

@songoow songoow commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Outcome basis / optional anchor: reproduced defect (no issue).
  • Goal/source and gap: (1) The workspace calls /api/ssh-source/ensure and /api/ssh-source/goal-lifecycle on the Chat service, but vite.config.ts only proxied /api/chat and /api/actions, so under npm run dev these requests hit a Vite 404. (2) The dashboard README said npm run dev:web opens the workspace "with the bundled example"; the workspace always requests /status.json through the proxy (the example mode in dashboard-page.tsx is never entered), so a fresh clone following the README lands on a status-load error (HTTP 502).
  • Observable before → after: POST /api/ssh-source/ensure through the dev server returned 404 from Vite; it now reaches the Chat service (400 host alias is required for an empty body). The README now describes what dev:web serves and which services it needs.
  • Issue/task and intended base: none; base main.

Scope And Continuation

  • Completed scope and remaining work: complete within this scope (dev proxy entry and two README paragraphs).
  • Slice boundary / successor: making the bundled example actually selectable in the workspace would change its first screen and needs an owner-reviewed preview; not attempted here. npm run smoke:demo-readiness -- --skip-browser, which the README keeps, currently fails on main in smoke:home-route (missing explicit Goal form action, after feat(chat): integrate conversational goal drafts into the existing workspace #4376 moved Goal creation into goal-create-request.ts); unrelated to this change.

Validation

  • Tested revision: ca89d0d
  • Run state: finished
  • Input classes: synthetic
Check kind Result Public-safe evidence / limitation
real_entrypoint passed Vite dev server from this branch in front of a real loopx chat (isolated synthetic registry): POST /api/ssh-source/ensure → Chat service 400; the same request through a dev server without the entry → Vite 404.
manual passed Fresh npm run dev:web without local services opens on the status-load error the README now describes.
integration failed Pre-existing on main: npm run smoke:demo-readiness -- --skip-browser fails in smoke:home-route as noted above.
  • Coverage and gaps: the proxy entry is exercised end to end; the README change is documentation only.

Frontend / Visual Evidence

  • UI impact: none

Type of Change

  • Bug fix
  • Documentation update

LoopX Area

  • Public docs or presentation surface (README, protocols, dashboard)

Technical Direction

  • Direction / acceptance reference, when applicable: Operator surface and IM integration.

Shared-authority RFC fixture impact

N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths.
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

Future-facing refactor pass: considered deriving the dev proxy table from the Chat service's route constants; unnecessary for one missing prefix.

The workspace calls /api/ssh-source/ensure and /api/ssh-source/goal-lifecycle
on the Chat service, but the dev proxy only forwarded /api/chat and
/api/actions, so these requests returned a Vite 404 under npm run dev.

Signed-off-by: song <liusongstep@gmail.com>
The README said dev:web opens the workspace on the bundled example. The
workspace always reads /status.json through the dev proxy, so without
loopx serve-status and loopx chat it opens on a status-load error. Say so,
and keep the bundled example as what smoke:demo-readiness validates.

Signed-off-by: song <liusongstep@gmail.com>
@huangruiteng
huangruiteng merged commit 738115b into loopx-project:main Sep 28, 2026
21 of 28 checks passed

@huangruiteng huangruiteng left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

状态回读补充:该 PR 已于 2026-09-28 17:58:09 UTC 合并,本次评审首次发布于 18:11:38 UTC,属于合并后的代码复核,不能作为事前合并授权。本任务没有执行合并操作。

未发现本次两文件改动引入的阻塞问题,代码结论为 APPROVE。在受测的 exact head 上,下面两项既有验证及严格质量资格仍失败;已合并的状态没有把这些证据改成通过。

动机

本次关闭两个已复现的开发入口缺口:同一个工作区页面通过 Vite 开发服务器运行时,已存在的 SSH 来源请求缺少对应代理,因此在到达 Chat 服务前就返回 HTTP 404;开发说明还错误承诺单独启动网页会自动展示示例。代理修复让现有调用到达原有处理器,文档修正则让首次启动、缺少服务和恢复读取的行为可预期。这是完整的开发入口修复,不以扩大远端生命周期功能作为前置条件。

改动思路

沿用既有 Vite 代理表,将 SSH 来源请求送到本机 Chat 服务;前端继续使用已有类型化客户端,服务端继续负责浏览器来源检查、SSH Host 目录校验、参数验证和远端操作。开发启动脚本仍分别启动状态与 Chat 服务,没有新增业务状态、协议版本或决策源。最强反例是无 Origin 的空请求可以到达处理器,而真正的浏览器调用仍被拦截;本次通过真实 Vite、临时 registry 下的原生 Chat CLI 和浏览器中的实际 SDK 排除了这个反例。隔离仅替换本机测试端口,没有替换处理器或伪造成功响应。

具体改动

完整差异为两个文件,增加十五行、删除十三行。其中四行是开发代理配置,其余是开发说明;没有生成文件、依赖变化或业务实现迁移。

关键代码讲解

  • Vite 的 SSH 代理项把接口族转发到既有 Chat 端口,沿用既有的 changeOrigin 设置,浏览器 Origin 检查仍有效。其余五项代理、监听地址、默认端口和 preview 配置均与 base 相同,因此修复落在实际缺失的开发传输边界。
  • ensureSshSource由来源添加和选择流程调用。它发送 Host 与本地端口,再读取原有结果;实际浏览器在 base 上收到代理错误,在 head 上成功复用已经响应的状态服务,界面显示来源已连接且为 SSH 只读投影。
  • applyRemoteGoalLifecycle继续校验返回的 Goal、Host、操作和投影验证标志。新增代理没有放宽这些校验;未知 Host 和非法操作通过真实处理器返回原有错误,任意新子路由仍返回未知路径。

README 对服务缺失的描述与浏览器实测一致:仅启动 Vite 时明确显示实时状态加载失败;启动隔离的原生状态服务后点击重试,可以恢复 Goal 状态读取。这个恢复检查不声称 Chat 会话或远端 SSH 生命周期也已完成验收。

对主干的风险

主要风险是新增代理可能改写浏览器来源,或者把整个接口前缀当成新的写入权限。实测保留了两条接口的来源拒绝、参数错误和未知路径处理;伪造 Origin 即使同时提交坏 JSON,也先被原有来源检查拒绝。SSH Host 目录、生命周期决策及远端命令仍在原有 owner 内;没有新增泛化状态分类、文本 denylist 或机器义务。生产 dashboard 与当前 Chat 入口资产在 base/head 上逐字节相同,开发配置也没有扩散到安装后的工作区。

本地验证 结果与边界
npm run build;uv run --extra test python scripts/chat_bundle.py verify --source base/head 均通过;生产 dashboard 文件和当前 Chat 入口资产一致
真实 Vite 与原生 Chat CLI 的同一组代理探针 Node 24.21.0、最低支持版本 22.22.3 各二十八项记录通过;另十二项路由范围与拒绝优先级检查通过
实际浏览器 SDK、来源添加、服务缺失与重试 通过;没有启动新 SSH 隧道或执行远端生命周期写入
npm run smoke:status-sources;uv run --extra test python -m pytest -q tests/test_ssh_tunnel_source.py 来源 smoke 和十项 transport 测试通过;单元测试作为真实 HTTP 证据的补充
canary premerge 选出的本地检查 十五项仓库检查和三个 diff 检查通过;整体合并资格仍不通过
npm run smoke:demo-readiness -- --skip-browser base/head 均失败:home-route 仍期待旧的内联 Goal 创建分支
node apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-contract.test.mjs base/head 均失败:仍期待旧的内联工作区字段;完整 packaged 浏览器 suite 未被记为通过

语义与 CI 对齐

两项红检查的完整日志仅归一化 checkout 路径后完全相同,其失败 owner、共享表单和验证代码不在本次差异内;本次请求传输不变量有独立通过的真实路径证据。相关旧断言已有独立修复方向,例如 #5265,但不能继承其尚未集成的测试结论。按当前评审契约,可以批准这个修复并保留独立的合并 HOLD;精确范围质量回执实际为失败,未缩小扫描、放宽预算或跳过检查来转绿。未查询、轮询或等待远端 CI。

我的整体评价

该实现复用了已有 owner,四行配置是当前最小完整修复;未来简化检查没有发现值得在这次添加的代理生成器或兼容层。持续使用方面,来源选择与重复调用不再因开发代理缺失而中断,失败和重试仍由原有状态读取流程处理;用户体验方面,首次启动说明与真实错误、恢复操作一致。剩余限制是两处原有验证失败,以及本次没有资格认定真实远端 SSH 创建或生命周期写入已验证。维护者仍需在相关检查修复或集成后重新验证对应范围;这份事后代码复核不追认合并前的流程或质量资格。本任务没有合并。

English verdict: APPROVE. The exact-head change restores the existing development transport and corrects the startup instructions. Real Vite/native Chat and browser checks pass. Independently reproduced, unchanged baseline validator failures keep the tested head’s strict quality qualification non-passing. This is a post-merge code audit, not prior merge authorization; live remote SSH lifecycle execution is not claimed.

@huangruiteng

huangruiteng commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

框架对齐记录:评审 head ca89d0da1c8625f2c4c7cf54e336785fab632490。

按 CONTRIBUTING 的贡献入口规则,这属于可以直接交付的自包含复现缺陷:原有工作区请求在开发代理处丢失,以及启动说明不符合现有默认行为。不需要为这个修复创建形式上的 roadmap 项。

归属符合 AGENTS 的 Goal、能力放置与有界简化要求:Vite 只补传输,状态与 SSH 操作继续由原有 owner 决策。已检查现有调用、默认路径、浏览器 Origin、来源只读反馈和错误恢复;本次不增加第二状态源或扩大远端权限。未来简化检查结论为无需额外抽象。

按 测试与质量指南,真实调用证据与单元测试分开报告,原有红检查保留为红,未将未验证的远端操作或完整 packaged suite 记为通过。状态回读显示 PR 已于 2026-09-28 17:58:09 UTC 合并,早于这份评审首次发布;代码 APPROVE 是事后复核,不是事前合并授权。受测 exact head 的严格质量资格仍失败,后续检查修复需要独立验证。本任务没有执行合并,也没有声称关闭更广的安装、远端生命周期或持续运行验收。

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