feat(site): 并入 Gin 官网与文档服务,对齐桌面产品形态
CI / Lint & TypeCheck (push) Canceled after 0s
CI / Test (push) Canceled after 0s
CI / Tauri Foundation Acceptance (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Build (windows-latest) (push) Canceled after 0s
CI / Lint & TypeCheck (push) Canceled after 0s
CI / Test (push) Canceled after 0s
CI / Tauri Foundation Acceptance (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Build (windows-latest) (push) Canceled after 0s
- apps/server:Gin embed 官网 + /docs + /health + /download(无操作 API) - run.sh 重写 web/gui 场景;.gitignore 排除 server 二进制与挂载的安装包 - README/AGENTS/CLAUDE 同步「浏览器只看官网、操作走桌面」的产品形态说明 - 终端视口背景变量与全宽终端边缘 hairline 修正(serial/terminal/i18n 微调)
This commit is contained in:
1 parent
b18214e96a
commit
5eb11826db
36 files changed
+3676
-144
No files matched your search
@@ -1,80 +1,93 @@
|
||||
# OpsXShell 开发指南
|
||||
|
||||
OpsXShell 是基于 Tauri 2、Rust、React 和 TypeScript 的轻量运维终端。产品强调便捷、人性化、操作简单实用,不加入审计、审批或堡垒机功能。
|
||||
轻量运维**桌面**终端(Tauri 2 + Rust + React + TS)。强调短路径好用;**不做**审计、审批、堡垒机。
|
||||
|
||||
## 架构
|
||||
请使用中文沟通。改功能后优先 `npm run test:patrol`。
|
||||
|
||||
- `src/`:React 界面、Zustand 状态和 XTerm.js 终端。
|
||||
- `src/i18n/`:界面文案(zh-CN / zh-TW / en / ja / ko / vi / ru);新增可见字符串必须同步全部语种,并用 `test/i18n/localeKeys.test.ts` 校验 key 对齐。
|
||||
- `src/platform/`:唯一的 Tauri 命令与事件适配入口。
|
||||
- `src/platform/sftp.ts`:固定 `localPath`/`remotePath` 方向,区分远程文本读写与文件传输。
|
||||
- `src/platform/rdp.ts` / `src/platform/vnc.ts`:远程桌面会话适配;运行态只在原生侧内存中。
|
||||
- `src/utils/terminalPipeline.ts`:终端输入、UTF-8 输出、背压和错误边界。
|
||||
- `src-tauri/src/commands/`:精简命令边界和统一响应。
|
||||
- `src-tauri/src/services/`:SSH、SFTP、隧道、PTY、串口、桌面、存储和凭据服务。转发 Listener 必须由 `TunnelManager` 统一持有和取消。
|
||||
- `src-tauri/src/services/ssh/`:认证、known_hosts、代理/跳板、路径和 SFTP,禁止重新堆回 `ssh.rs`。
|
||||
- `src-tauri/src/services/tunnel/`:运行模型、SOCKS5 协议和 Relay;运行态只能由 `TunnelManager` 持有。
|
||||
- `src-tauri/src/services/desktop/`:RDP(IronRDP)与 VNC(vnc-rs);帧、输入、剪贴板经 Tauri 事件交给 Canvas,断开即取消 worker。RDP 批量压缩优先 RDP5(MPPC/K64),避免 XCRUSH 在分辨率切换后解压失败。
|
||||
- `shared/types/`:渲染层共享 TypeScript 契约。
|
||||
- `test/`:Vitest 单元/组件测试与基础巡检(`test/patrol/`:SSH / SFTP / RDP / VNC);改功能后优先 `npm run test:patrol`。
|
||||
- `scripts/`:本地启动、验收、版本同步与原生安装包构建/发布脚本(入口 `./run.sh`、`./scripts/build.sh`)。
|
||||
- `docs/`:使用、架构、验收与发布文档;路线图与任务见根目录 `ROADMAP.md` / `TASKS.md` / `TDD_PLAN.md`。
|
||||
## 产品形态(硬边界)
|
||||
|
||||
React 不直接访问 SSH、文件系统或加密实现。数据流:UI → Zustand → `src/platform/*` → Tauri command → `src-tauri` 服务。新增原生能力时先定义 Rust command,再更新 `src/desktop.d.ts`、对应 `src/platform/*.ts` 和 `test/setup.ts`。
|
||||
```text
|
||||
浏览器 → 只看官网 + 文档(Gin :8789)
|
||||
操作 → 只走桌面 Tauri(./run.sh gui)
|
||||
Vite :1420 → 仅桌面 WebView 源,不是浏览器产品
|
||||
```
|
||||
|
||||
## 怎么扩展
|
||||
| 职责 | 放哪 |
|
||||
| -------------------------------------------------- | --------------------------------------------------------------- |
|
||||
| 桌面操作(SSH/SFTP/转发/RDP/VNC/串口/本地终端/AI) | **本仓** `src/` + `src-tauri/` |
|
||||
| 产品官网 + 用户文档 | **本仓** `apps/server`(Gin embed;原 `site-opsxshell` 已并入) |
|
||||
| 结账 / 在线授权 | 独立服务 **opsx-licence**;桌面只验 `LIC-` / `LICOFF-` |
|
||||
|
||||
1. 领域契约:先改 `shared/types/` 或 Rust domain,再改 command。
|
||||
2. 原生实现:能力放 `src-tauri/src/services/`,command 只做参数边界和统一响应。
|
||||
3. 渲染适配:只经 `src/platform/`;组件和 store 不直接 `invoke`。
|
||||
4. 界面:Zustand 持有资源 ID 与 UI 状态;可见文案同步七语种。
|
||||
5. 测试:功能改动优先 `npm run test:patrol`,再补对应单测。
|
||||
同族对照:**opsxdb / opsxapi** 同形态(浏览器=官网/docs,操作=桌面)。Shell 的 Gin **只有** site/docs/health/download,**没有**操作 API——原生能力全在 Rust。
|
||||
|
||||
## IPC 响应约定
|
||||
`src/` 里的 React 是 **Tauri WebView UI**,不是浏览器 SaaS 客户端。
|
||||
|
||||
- 业务失败(SSH / SFTP / 转发 / 会话 CRUD / 本地文件)使用信封 `{ success, error, errorCode? }`。`errorCode` 是稳定点分路径(如 `native.taskJoin`),前端用 `translateIpcError` 映射 `errors:*`。
|
||||
- RDP / VNC 运行态(connect / input / clipboard)走 throw;在桌面视图 catch。
|
||||
- 禁止第三种失败形态。组件和 store 不直接 `invoke`,只经 `src/platform/`(`invokeNative` / `invokeEnvelope`)。
|
||||
- 同步对话框 command(`show_open_dialog` / `show_save_dialog`)必须在主线程调用,不得 `spawn_blocking`(macOS 保存框依赖主线程)。磁盘 I/O 走 `spawn_blocking`。
|
||||
### 目录对齐说明
|
||||
|
||||
## 规则
|
||||
- 已对齐:`apps/server`(Gin 官网+docs)、`./run.sh web|gui` 场景。
|
||||
- **暂不**把 `src/` / `src-tauri/` 物理迁到 `apps/web` / `apps/desktop`(db/api 的 monorepo 布局);语义已统一,大挪目录收益小、打断现有打包与 CI。需要时再单独立项。
|
||||
|
||||
- 未由 Rust 后端实现的能力不能在界面中显示为可用。
|
||||
- 会话密码、私钥口令和代理密码必须由 Rust 加密后落盘。
|
||||
- 不保存终端命令历史;批量命令结果仅保留在当前窗口。
|
||||
- 主机密钥使用 `~/.ssh/known_hosts` 校验。
|
||||
- 主密钥位于 `~/.opsxshell/master.key`,Unix 目录权限 `0700`、文件权限 `0600`。
|
||||
- 保持常用流程简短,高级配置默认收起。
|
||||
- 端口转发规则可持久化,运行中状态不得持久化;界面的停止操作必须关闭真实原生 Listener。
|
||||
- 复制转发规则不得复制运行态;运行中的规则修改前必须先停止 Listener。
|
||||
- SSH 断开 / keepalive 失败 / 空闲挂起 / 同窗重连:未点「停止」的转发 Listener 应保留;按 `user@host:port` 指纹 orphan-adopt;同窗用进程内 `forwardIntent` 自动恢复;关标签不得自动再启。空闲挂起应先断开原生会话并 `retainForwards`,避免僵尸 TCP。
|
||||
- SSH 标签还开着时:协议心跳保链路(不写入 Shell,不对抗 TMOUT);意外断开有限次自动重连(新 PTY)。远端空闲退出只提示重开该分屏。不要默认向 Shell 发送回车/空格。长任务用远端 tmux/screen。
|
||||
- 活跃 SFTP 标签同样有限次自动重连并恢复上次远程目录。
|
||||
- RDP/VNC 标签还开着时意外断开有限次自动重连;不发送假鼠标对抗空闲 GPO。断开即取消本地 worker,重连是新会话。
|
||||
- 动态转发(SOCKS5)默认仅本机 `127.0.0.1:1080`;流量经当前 SSH 服务器出口 IP 访问外网。每台 SSH 主机仅保留一条动态规则。状态栏「转发」打开抽屉管理,右键复制 `socks5://127.0.0.1:1080`。
|
||||
- 本地转发监听默认本机端口;远程转发监听默认远端 `127.0.0.1`。远程 `0.0.0.0` 需 sshd `GatewayPorts`,未开启时常静默只绑 loopback。
|
||||
- SFTP read/write 不得作为 upload/download 的别名,本地路径与远程路径不得使用位置含糊的调用。
|
||||
- RDP / VNC 仅在 Tauri 原生应用中可用;会话运行态不落盘,断开即清理。批量命令排除桌面会话。
|
||||
- 大模型新配置必须先用临时凭据完成真实测试,测试期间不得写 settings 或 secrets;连接字段变化后保存必须重新锁定。
|
||||
- AI 远程执行只能复用当前活跃 SSH connection;按 strict/relaxed(严格/宽松)模式决定确认阈值,critical 始终硬拒绝;不建立独立 podexec/Kubernetes 凭据边界,也不保存命令或工具输出。
|
||||
- `ssh://` 禁止携带密码或静默直连;冷启动与运行中唤起都必须通过原生有界队列交付给快速连接确认。
|
||||
## 架构(怎么改代码)
|
||||
|
||||
```text
|
||||
UI / Zustand → src/platform/* → Tauri command → src-tauri/services/*
|
||||
apps/server → Gin:/ 官网 · /docs · /health · /download(无操作面)
|
||||
```
|
||||
|
||||
- `src/platform/`:唯一 `invoke` / 事件入口;组件与 store **不直接** `invoke`。
|
||||
- `src-tauri/src/commands/`:参数边界 + 统一响应;业务在 `services/`。
|
||||
- `shared/types/`:前后端契约;新能力先契约再 command,再补 `desktop.d.ts` / `platform` / `test/setup.ts`。
|
||||
- 文案:`src/i18n` 七语种同步;`test/i18n/localeKeys.test.ts` 校验 key。
|
||||
- 官网 HTML:`apps/server/internal/site/`;用户文档 Markdown:`apps/server/internal/docs/content/`(改完重编 server)。
|
||||
|
||||
扩展顺序:契约 → services → command → platform → UI → 测试。
|
||||
|
||||
### IPC
|
||||
|
||||
- 业务失败(SSH/SFTP/转发/会话/本地文件):信封 `{ success, error, errorCode? }`。
|
||||
- RDP/VNC 运行态:throw,视图里 catch。
|
||||
- 文件对话框 command 须在主线程;磁盘 I/O 用 `spawn_blocking`。
|
||||
|
||||
## 硬边界(少而硬)
|
||||
|
||||
1. 界面不展示 Rust 未实现的能力。
|
||||
2. 密码 / 私钥口令 / 代理密码:Rust 加密落盘;主密钥 `~/.opsxshell/master.key`(Unix `0700`/`0600`)。
|
||||
3. 不保存终端命令历史;批量结果仅当前窗口。
|
||||
4. known_hosts 校验;`ssh://` 禁止带密码或静默直连(走快速连接确认队列)。
|
||||
5. 转发:规则可持久化,**运行态不落盘**;停止必须关掉真实 Listener;改运行中规则先停 Listener。
|
||||
6. 会话运行态(SSH/转发/RDP/VNC worker)只在原生内存;断开即清理桌面 worker。
|
||||
7. 不把结账/签发、CLI/MCP/插件宿主、堡垒机审批做成默认能力。
|
||||
8. 不恢复旧 Electron 桌面壳、旧构建链。
|
||||
9. **不要**把桌面操作做成浏览器工作台;`:1420` 不是对外入口。
|
||||
|
||||
## 领域要点(细节跟现有代码,勿另起炉灶)
|
||||
|
||||
- **隧道**:`TunnelManager` 统一持有/取消;同窗重连可 orphan-adopt / `forwardIntent`;关标签不自动再启。SOCKS5 默认 `127.0.0.1`,每主机一条动态规则。
|
||||
- **SSH/SFTP**:协议心跳保链路(勿向 Shell 灌回车空格);意外断开有限次重连;SFTP 分清 upload/download 与路径方向。
|
||||
- **RDP/VNC**:仅桌面端;有限次重连;压缩/帧路径跟 `services/desktop/`,勿新开解压栈。
|
||||
- **AI**:新配置先临时凭据实测再落盘;远程执行只复用当前 SSH;critical 硬拒绝。
|
||||
- **授权**:只对接 opsx-licence;本地验 `LIC-` / `LICOFF-`。
|
||||
|
||||
实现时优先对照邻近模块与单测,而不是在本文件追加细则。
|
||||
|
||||
## 命令
|
||||
|
||||
```bash
|
||||
./run.sh # 开发启动(scripts/run.sh)
|
||||
npm run test:patrol
|
||||
npm run acceptance:quick
|
||||
npm run acceptance:full
|
||||
./scripts/build.sh # 当前平台安装包(macOS → Tauri .app + .dmg)
|
||||
./scripts/macos-notarize.sh # 新 DMG 的 Apple 公证 + staple
|
||||
./run.sh # = web:官网 + docs → :8789
|
||||
./run.sh web # 同上
|
||||
./run.sh gui # 桌面操作入口(默认顺带起 Gin)
|
||||
./run.sh stop | status
|
||||
npm run test:patrol # 改功能优先
|
||||
npm run acceptance:quick # 或 acceptance:full
|
||||
./scripts/build.sh # 当前平台安装包 → release/
|
||||
./scripts/macos-notarize.sh # 新 DMG 公证(有凭据时)
|
||||
```
|
||||
|
||||
平台安装包必须在目标系统实机验收。没有签名凭据时不得宣称完成签名、公证或自动更新发布。macOS 有 Developer ID 时:仓库默认 `signingIdentity` 仍是 `"-"`;本机把身份写进 gitignore 的 `src-tauri/tauri.signing.conf.json`,`build.sh` 会自动带上,并走 `bundle.macOS.dmg` 的 Tauri 窗口布局。新打的 DMG 必须再跑 `macos-notarize.sh` 才能给别人直接打开。
|
||||
无签名凭据时不要宣称已签名/公证/自动更新。打包须在目标 OS 实机验收。
|
||||
|
||||
## 评审边界
|
||||
## 给 AI 的协作原则
|
||||
|
||||
- `src/platform/` 与 Tauri command 是本应用内部边界,不是给第三方调用的公共 API。
|
||||
- 结账与在线授权由独立的 opsx-licence 服务承担;不要把结账/签发逻辑堆回桌面进程。桌面端只验 `LIC-`(在线)和 `LICOFF-`(离线 Ed25519)。
|
||||
- 不把 CLI、MCP、插件宿主或堡垒机审批做成默认能力。
|
||||
- 转发 Listener、SSH 会话、RDP/VNC worker 的运行态只在原生侧内存;评审时以「停止是否关掉真实资源」为准。
|
||||
- **先做再问**:需求清楚就直接改;不确定时用最小假设推进,并在回复里写明假设。
|
||||
- **跟仓内模式**:新功能对齐现有 `platform` / `services` 分包,禁止平行架构。
|
||||
- **少造文档**:非用户要求不要新增长篇 markdown;改行为同步必要注释即可。
|
||||
- **测试够用**:功能改动跑 patrol + 相关单测;不必为每个微规则再加一篇规范。
|
||||
Reference in new issue
Block a user