chore: 保存 Agent 安全优化前基线
This commit is contained in:
1 parent
08696896f9
commit
ff016347cd
116 files changed
+3858
-2485
No files matched your search
+11
-10
@@ -2,15 +2,16 @@
|
||||
|
||||
文档按使用、开发、验收和发布分开维护,避免把规划能力写成已支持功能。
|
||||
|
||||
| 文档 | 内容 |
|
||||
| -------------------------------------------- | ------------------------------------------------- |
|
||||
| [使用指南](./user-guide.md) | SSH、SFTP、代理、串口、AI 助手和数据安全 |
|
||||
| [架构说明](./architecture.md) | Tauri/Rust 分层、原生服务、AI 与安全边界 |
|
||||
| [SSH Agent CLI](./ai-agent.md) | ReAct 执行循环、工具、风险、记忆取舍与评测 |
|
||||
| [测试验收](./testing-acceptance.md) | 本地门禁、真实 SSH 探针和发版验收 |
|
||||
| [发布指南](./release.md) | macOS/Windows 构建、签名、产物和临时文件清理 |
|
||||
| [路线图](../ROADMAP.md) | 已完成基线与下一阶段(根目录权威副本) |
|
||||
| [当前任务](../TASKS.md) | Hermes / OpenClaw 可勾选任务 |
|
||||
| [测试计划](../TDD_PLAN.md) | 巡检、门禁与下一任务的测试先行 |
|
||||
| 文档 | 内容 |
|
||||
| ------------------------------------------ | ----------------------------------------------------- |
|
||||
| [使用指南](./user-guide.md) | SSH、SFTP、代理、串口、AI 助手和数据安全 |
|
||||
| [架构说明](./architecture.md) | Tauri/Rust 分层、原生服务、AI 与安全边界 |
|
||||
| [架构重构轨道](./architecture-refactor.md) | EventSink / specta / infrastructure(未开始,单独做) |
|
||||
| [SSH Agent CLI](./ai-agent.md) | ReAct 执行循环、工具、风险、记忆取舍与评测 |
|
||||
| [测试验收](./testing-acceptance.md) | 本地门禁、真实 SSH 探针和发版验收 |
|
||||
| [发布指南](./release.md) | 构建与产物;签名/公证/自动更新的做法(当前未完成) |
|
||||
| [路线图](../ROADMAP.md) | 已完成基线与下一阶段(根目录权威副本) |
|
||||
| [当前任务](../TASKS.md) | Hermes / OpenClaw 可勾选任务 |
|
||||
| [测试计划](../TDD_PLAN.md) | 巡检、门禁与下一任务的测试先行 |
|
||||
|
||||
项目定位、功能概览和开发命令见仓库根目录的 [README](../README.md),未完成事项只在 [ROADMAP.md](../ROADMAP.md) / [TASKS.md](../TASKS.md) 维护。
|
||||
+9
-9
@@ -51,15 +51,15 @@ OpsXShell 适合吸收 aiops Agent CLI 的执行 Harness,不适合照搬它的
|
||||
|
||||
### 安全边界
|
||||
|
||||
| 等级 | 示例 | 严格模式 | 均衡模式(默认) | 宽松模式 |
|
||||
| -------- | --------------------------------- | -------- | ---------------- | -------- |
|
||||
| safe | `df -h`、`journalctl -u nginx` | 自动执行 | 自动执行 | 自动执行 |
|
||||
| low | 未知自定义查询命令 | 自动执行 | 自动执行 | 自动执行 |
|
||||
| medium | 文件写入、普通权限变更 | 先确认 | 自动执行 | 自动执行 |
|
||||
| high | 服务重启、删除、包安装、K8s 变更 | 先确认 | 先确认 | 自动执行 |
|
||||
| critical | 格式化磁盘、删除根目录、fork bomb | 硬拒绝 | 硬拒绝 | 硬拒绝 |
|
||||
| 等级 | 示例 | 严格模式 | 宽松模式(默认) |
|
||||
| -------- | --------------------------------- | -------- | ---------------- |
|
||||
| safe | `df -h`、`journalctl -u nginx` | 自动执行 | 自动执行 |
|
||||
| low | 未知自定义查询命令 | 自动执行 | 自动执行 |
|
||||
| medium | 文件写入、普通权限变更 | 先确认 | 自动执行 |
|
||||
| high | 服务重启、删除、包安装、K8s 变更 | 先确认 | 先确认 |
|
||||
| critical | 格式化磁盘、删除根目录、fork bomb | 硬拒绝 | 硬拒绝 |
|
||||
|
||||
安全模式在任务开始时锁定,运行中不能切换;需要确认时,对话框必须显示本次锁定模式、目标、风险和完整单行命令。宽松模式明确标注“仅适合隔离测试环境”,它不会降低 critical 硬红线。
|
||||
安全模式在任务开始时锁定,运行中不能切换;需要确认时,对话框必须显示本次锁定模式、目标、风险和完整单行命令。critical 在前端与 Rust `guardrail` 都会硬拒绝。旧文档里的「均衡 / 宽松第三级」已合并为宽松。
|
||||
|
||||
终端输出被标记为不可信数据,不得将日志中的“忽略规则”等文字当作指令。常见密码、Token、Authorization Header、AWS Key 和私钥块在 Rust 发送 Provider 前脱敏。
|
||||
|
||||
@@ -77,7 +77,7 @@ OpsXShell 适合吸收 aiops Agent CLI 的执行 Harness,不适合照搬它的
|
||||
| ReAct 16 轮 | 适配为 8 步 | GUI 前台执行,优先快速收敛 |
|
||||
| 失败反馈和循环检测 | 已吸收 | 退出码和真实输出回传,连续失败换路,相同命令限次 |
|
||||
| 五级风险 | 已吸收 | critical 硬拒绝,其他等级按安全模式阈值确认 |
|
||||
| 三级安全模式 | 已适配 | 严格从 medium、均衡从 high 确认;宽松仍不可绕过 critical |
|
||||
| 两级安全模式 | 已适配 | 严格从 medium、宽松从 high 确认;critical 前后端均硬拒绝 |
|
||||
| WebSocket 事件流 | 不照搬 | 本地 React/Tauri 没有跨程服务器会话,使用内存状态即可 |
|
||||
| 审计、审批、RBAC | 不引入 | 属于 aiops/堡垒机,不是本地 SSH 客户端职责 |
|
||||
| podexec/K8s 专用工具 | 不引入 | `kubectl/helm` 可沿远程 SSH 工具使用,不引入第二套目标和凭据边界 |
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# 架构重构(单独轨道,尚未开始)
|
||||
|
||||
**当前不要做。** 改动面覆盖几乎全部 `src-tauri` 服务、`src/desktop.d.ts`、`src/platform/*` 和测试替身。本文件只记录怎么拆,避免和日常功能 PR 缠在一起。
|
||||
|
||||
当前真实分层是 **commands → services → domain DTO**。目录里虽有 `application/`、`infrastructure/`,但:
|
||||
|
||||
- `infrastructure/` 只有 `file_log`,services 并不走它。
|
||||
- `application/state.rs` 是服务集合,不是端口组合根。
|
||||
- `DomainError` 零引用。
|
||||
- SSH / 存储 / 桌面服务直接 `use tauri::AppHandle`;known_hosts 还用 `bind_app_handle` 全局 static。
|
||||
- 前后端契约靠手写 `src/desktop.d.ts` + `shared/types/`,没有 specta / ts-rs。
|
||||
|
||||
产品数据流保持不变:UI → Zustand → `src/platform/*` → Tauri command → Rust 服务。重构不得把 SSH、文件系统或加密拉回 React,也不得改成插件宿主。
|
||||
|
||||
## 为什么单独做
|
||||
|
||||
1. EventSink 要改所有 `app.emit` 调用点,和功能修复冲突时极难回滚。
|
||||
2. specta 会动 command 签名和前端 `invoke` 形状,必须一次对齐 CI,不能「先生成一半」。
|
||||
3. 把 storage / SSH / 凭据收进 infrastructure trait,等于重写生命周期,和转发 retain、桌面 worker 取消语义绑在一起。
|
||||
|
||||
一次只开一条轨道,合入后再开下一条。每条轨道自己的 PR,跑 `npm run test:patrol` 和 `npm run acceptance:full`。
|
||||
|
||||
## 轨道 A:EventSink(先做,最小)
|
||||
|
||||
目标:services 不再拿 `AppHandle`,也不再 `bind_app_handle`。
|
||||
|
||||
1. 在 `application/` 定义:
|
||||
|
||||
```rust
|
||||
pub trait EventSink: Send + Sync {
|
||||
fn emit_json(&self, channel: &str, payload: serde_json::Value);
|
||||
fn emit_empty(&self, channel: &str);
|
||||
}
|
||||
```
|
||||
|
||||
2. `TauriEventSink(AppHandle)` 只放在 application / command 边界。
|
||||
3. `SshService`、known_hosts、RDP/VNC engine、license 等改为持有 `Arc<dyn EventSink>`。
|
||||
4. 删除 `known_hosts` 的 `APP_HANDLE` / `PENDING` / `ONCE_TRUSTED` 全局 static,收进 `AppState`。
|
||||
5. 单测用内存 `EventSink` 断言事件,不启 Tauri。
|
||||
|
||||
完成标准:`rg "use tauri::AppHandle" src-tauri/src/services` 为空(command 层可以留)。行为与现网事件名、payload 完全一致。
|
||||
|
||||
## 轨道 B:契约生成(specta 或 ts-rs)
|
||||
|
||||
目标:消灭「Rust DTO / `desktop.d.ts` / `shared/types`」三处手工对齐。
|
||||
|
||||
1. 选一个:`tauri-specta`(和 command 绑定)或 `ts-rs`(只生成类型)。不要两个一起上。
|
||||
2. Rust 侧先把 `serde_json::Value` 逃逸收成强类型(`ProxyConfig`、`JumpHostConfig`、会话字段)。
|
||||
3. 生成文件放到例如 `shared/types/*.generated.ts`,CI 跑 `git diff --exit-code`。
|
||||
4. 手写 `src/desktop.d.ts` 只留窗口/`opsxApi` 外壳,领域类型改 re-export 生成结果。
|
||||
5. `test/setup.ts` 跟着生成类型改,不要继续复制一份松散 `unknown`。
|
||||
|
||||
完成标准:改一个 command 字段,忘跑生成则 CI 红。不要在这一轨改 EventSink 或换存储引擎。
|
||||
|
||||
## 轨道 C:infrastructure 端口(最后)
|
||||
|
||||
目标:I/O 可替换,services 只编排。
|
||||
|
||||
建议端口(按需,不要一次全铺):
|
||||
|
||||
| Trait | 先搬谁 | 不要顺便做 |
|
||||
| -------------- | ---------------------------------- | ----------------------- |
|
||||
| `SessionStore` | `services/storage.rs` 的 JSON 会话 | 不要同时改成 SQLite |
|
||||
| `SecretStore` | `credential_store.rs` | 不要同时改系统 keychain |
|
||||
| `SshTransport` | 仅当要换 russh 时再抽 | 默认保持 libssh2 |
|
||||
|
||||
`infrastructure/mod.rs` 里现在的「SQLite / keychain / PTY 适配器」是过期注释,做 C 轨时改成与真实 trait 一致,没做的删掉,避免再写成已存在。
|
||||
|
||||
`DomainError`:有调用方再留,否则删。不要为空壳再加一层错误类型。
|
||||
|
||||
## 明确不做(本轨道也不做)
|
||||
|
||||
- 六边形/整仓重命名目录来「看起来像五层」。
|
||||
- 对外 CLI、MCP、插件宿主。
|
||||
- 把结账/签发搬回桌面进程。
|
||||
- 和签名、公证、自动更新、功能修复混在同一个 PR。
|
||||
+17
-16
@@ -51,20 +51,20 @@ services/
|
||||
|
||||
## 原生服务
|
||||
|
||||
| 能力 | 实现 |
|
||||
| -------------------- | ------------------------------------------------ |
|
||||
| SSH/SFTP | `ssh2 0.9` / libssh2 |
|
||||
| HTTP/SOCKS5 连接代理 | Rust TCP 握手后交给 libssh2 |
|
||||
| ProxyJump | libssh2 direct-tcpip + loopback relay,最多 8 跳 |
|
||||
| 本地/远程/动态转发 | libssh2 channel + Rust TCP relay |
|
||||
| RDP | IronRDP(帧 / 输入 / Cliprdr / RDPDR) |
|
||||
| VNC | `vnc-rs` RFB |
|
||||
| 本地终端 | `portable-pty` |
|
||||
| 串口 | `serialport` |
|
||||
| 会话与设置 | 应用数据目录内原子写入 JSON |
|
||||
| 凭据 | AES-256-GCM + `~/.opsxshell/master.key` |
|
||||
| 主机信任 | OpenSSH `~/.ssh/known_hosts` |
|
||||
| 终端 AI | Rust `reqwest` + OpenAI/Anthropic 兼容协议 |
|
||||
| 能力 | 实现 |
|
||||
| -------------------- | ------------------------------------------------------------------- |
|
||||
| SSH/SFTP | `ssh2 0.9` / libssh2 |
|
||||
| HTTP/SOCKS5 连接代理 | Rust TCP 握手后交给 libssh2 |
|
||||
| ProxyJump | libssh2 direct-tcpip + loopback relay,最多 8 跳 |
|
||||
| 本地/远程/动态转发 | libssh2 channel + Rust TCP relay |
|
||||
| RDP | IronRDP(帧 / 输入 / Cliprdr / RDPDR) |
|
||||
| VNC | `vnc-rs` RFB |
|
||||
| 本地终端 | `portable-pty` |
|
||||
| 串口 | `serialport` |
|
||||
| 会话与设置 | 应用数据目录内原子写入 JSON |
|
||||
| 凭据 | AES-256-GCM + `~/.opsxshell/master.key` |
|
||||
| 主机信任 | OpenSSH `~/.ssh/known_hosts` |
|
||||
| 终端 AI | Rust `reqwest` + OpenAI/Anthropic 兼容协议 |
|
||||
| 界面语言 | i18next;zh-CN / zh-TW / en / ja / ko / vi / ru,首启按系统语言检测 |
|
||||
|
||||
## SSH Agent CLI 边界
|
||||
@@ -94,7 +94,7 @@ XTerm 当前焦点分屏
|
||||
- 新 Provider 的测试命令接收临时 API Key 并发出最小真实完成请求;测试过程不调用凭据存储。只有当前连接字段快照测试成功,界面才允许保存。
|
||||
- 模型返回内容按不可信文本处理;终端输出也标记为不可信,其中的指令不能覆盖 system Prompt。
|
||||
- Agent 只接受唯一单行命令,目标固定为当前活跃 SSH connection;本次运行开始后安全模式锁定,确认框必须显示目标、命令、风险和锁定模式。
|
||||
- 命令风险为 safe/low/medium/high/critical 五级。严格模式从 medium 起确认;默认均衡模式从 high 起确认;宽松模式仅适合隔离测试环境。格式化磁盘、删除根目录等 critical 操作在任何模式下都硬拒绝。
|
||||
- 命令风险为 safe/low/medium/high/critical 五级。严格模式从 medium 起确认;默认宽松模式从 high 起确认。格式化磁盘、删除根目录等 critical 操作在前端与 Rust guardrail 都会硬拒绝。
|
||||
- 相同命令第 3 次在执行前拦截;连续失败时要求更换排查路径。长输出先经本地 `analyze_output` 保留错误行和首尾。
|
||||
- 不创建独立 Kubernetes 客户端或 podexec。集群运维命令沿当前 SSH 会话执行,避免引入本机 kubeconfig 与第二套目标/凭据边界。
|
||||
|
||||
@@ -160,7 +160,8 @@ SSH 传输本身受协议 MAC 保护;当前应用额外执行大小校验,
|
||||
- 不持久化终端命令历史或批量命令输出。
|
||||
- 不持久化 AI 提示词、回答或终端上下文;API Key 不得返回 WebView 或写入普通 settings。
|
||||
- 未实现能力不能在界面中显示为可用。
|
||||
- 自动更新必须具备签名公钥、HTTPS 更新源和回滚策略,否则保持关闭。
|
||||
- 自动更新必须具备签名公钥、HTTPS 更新源和回滚策略,否则保持关闭。当前未接入 updater,做法见 [发布指南](./release.md#签名公证和自动更新未完成)。
|
||||
- 五层目录补全、specta、EventSink 是单独轨道,见 [架构重构](./architecture-refactor.md);未开始前继续按本文件的 commands → services → platform 扩展。
|
||||
- 应用不能静默绕过 changed host key 或 known_hosts 不匹配。
|
||||
|
||||
## 体积预算
|
||||
|
||||
+84
-13
@@ -87,25 +87,96 @@ lsof +D /Volumes/<临时卷名>
|
||||
|
||||
先正常退出该 OpsXShell 进程,再卸载对应的临时卷并重新构建。不要在应用仍从卷内运行时直接删除 `rw.*.dmg`。
|
||||
|
||||
## 签名和公证
|
||||
## 签名、公证和自动更新(未完成)
|
||||
|
||||
标签 `tauri-v*` 会触发 `.github/workflows/tauri-release.yml`。正式标签构建要求签名变量齐全。
|
||||
**当前状态:没有签名凭据,公开包是 ad-hoc / 未签名,未公证,没有自动更新。**
|
||||
没有 `APPLE_*` / Authenticode 证书、minisign 私钥和 HTTPS 更新源之前,不得在 README、界面、Release 说明或 CI 绿勾上写「已签名」「已公证」「支持自动更新」。`tauri.conf.json` 的 `signingIdentity` 现在是 `"-"`;`plugins` 只有 deep-link,没有 updater。
|
||||
|
||||
macOS:
|
||||
现有门禁只做「有凭据才验、没凭据就标明开发包」:
|
||||
|
||||
- `APPLE_CERTIFICATE`
|
||||
- `APPLE_CERTIFICATE_PASSWORD`
|
||||
- `APPLE_SIGNING_IDENTITY`
|
||||
- `APPLE_ID`
|
||||
- `APPLE_PASSWORD`
|
||||
- `APPLE_TEAM_ID`
|
||||
- `REQUIRE_SIGNING=true` 时,`scripts/release-preflight.mjs` 检查环境变量齐全,`scripts/verify-release.mjs` 拒绝 macOS ad-hoc、要求 Windows Authenticode `Valid`。
|
||||
- 未设该变量时,`./scripts/build.sh` 仍可打开发包,验证只检查架构和体积。
|
||||
- CI 工作流 `.github/workflows/tauri-release.yml` 已能在 Secrets 齐全时写入 `src-tauri/tauri.signing.conf.json` 再构建;**本地 `build.sh` 还不会生成这份配置**,所以本机即使导出了同样的环境变量,也不会走出 ad-hoc。
|
||||
- 全仓库没有 `notarytool` / `staple`。Developer ID 签过但未公证的 `.app`,用户机器上仍会被 Gatekeeper 拦。
|
||||
- `scripts/release.py` 仍提示「右键打开」——这是 ad-hoc 包的权宜说明,正式公证后必须删掉。
|
||||
|
||||
Windows:
|
||||
下面是有凭据之后的做法。没齐之前不要改 `signingIdentity`、不要接 updater 插件、不要在设置里放「检查更新」。
|
||||
|
||||
- `WINDOWS_CERTIFICATE_BASE64`
|
||||
- `WINDOWS_CERTIFICATE_PASSWORD`
|
||||
### 1. 凭据(先买/申请,再接线)
|
||||
|
||||
缺少凭据时只能生成开发构建,不能标记为正式签名或已公证版本。
|
||||
| 平台 | 要什么 | 放到哪里 |
|
||||
| -------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| macOS | Apple Developer Program;**Developer ID Application** 证书(`.p12`);App 专用密码 | 本机环境变量 + GitHub/Gitee Secrets:`APPLE_CERTIFICATE`(p12 的 base64)、`APPLE_CERTIFICATE_PASSWORD`、`APPLE_SIGNING_IDENTITY`(如 `Developer ID Application: …`)、`APPLE_ID`、`APPLE_PASSWORD`、`APPLE_TEAM_ID` |
|
||||
| Windows | 代码签名证书(OV/EV PFX) | `WINDOWS_CERTIFICATE_BASE64`、`WINDOWS_CERTIFICATE_PASSWORD` |
|
||||
| 自动更新 | 单独的 **minisign** 密钥对,与 Apple/Authenticode 不是同一把 | 私钥只进 CI Secrets;**公钥**写进仓库的 updater 配置 |
|
||||
|
||||
Linux 安装包(deb/rpm/AppImage)不走 Apple/Authenticode。自动更新的 `.sig` 是另一套签名,三平台都要。
|
||||
|
||||
`src-tauri/tauri.signing.conf.json` 由脚本现场生成,必须进 `.gitignore`,不得提交。
|
||||
|
||||
### 2. 本地与 CI 同源签名
|
||||
|
||||
目标:本机 `REQUIRE_SIGNING=true ./scripts/build.sh` 与 CI 走同一条路径,都能复现同一类签名产物。
|
||||
|
||||
1. `build.sh` / `build.bat` 在签名变量齐全时,生成 `tauri.signing.conf.json`(macOS 写 `bundle.macOS.signingIdentity`;Windows 写 thumbprint / sha256 / timestamp),再 `npx tauri build --config src-tauri/tauri.signing.conf.json`。
|
||||
2. 不要改仓库里的 `tauri.conf.json` 默认 `"-"`——没凭据的开发机构必须还能打 ad-hoc。
|
||||
3. `REQUIRE_SIGNING=true` 时 `verify-release.mjs` 必须失败于 ad-hoc / 无效 Authenticode;不要为了绿而关校验。
|
||||
4. 正式标签才设 `REQUIRE_SIGNING=true`。日常 PR 构建保持未签名。
|
||||
|
||||
### 3. macOS 公证(notarytool + staple)
|
||||
|
||||
签名成功 ≠ 用户能打开。必须公证并钉票:
|
||||
|
||||
```bash
|
||||
# 构建并 Developer ID 签名之后
|
||||
xcrun notarytool submit "$DMG" \
|
||||
--apple-id "$APPLE_ID" --password "$APPLE_PASSWORD" --team-id "$APPLE_TEAM_ID" \
|
||||
--wait
|
||||
xcrun stapler staple "$DMG"
|
||||
# 若 staple 的是 .app,再重新打 DMG,或对 DMG 再 staple
|
||||
spctl --assess --type install --verbose "$DMG"
|
||||
```
|
||||
|
||||
验收(必须在**另一台未关 SIP、未关 Gatekeeper 的 Mac**上,不要只在构建机看 `spctl`):
|
||||
|
||||
1. 下载 DMG,双击打开,拖到「应用程序」,**不要**右键「打开」、不要 `xattr -d`。
|
||||
2. 能启动、能连 SSH,菜单里没有 DevTools。
|
||||
3. `codesign --verify --deep --strict` 且 `codesign -dv` 不是 `Signature=adhoc`。
|
||||
4. 删掉 Release 说明和 `release.py` 里的「右键绕过 Gatekeeper」。
|
||||
|
||||
没做完 staple 之前,文档继续写「未公证」。
|
||||
|
||||
### 4. Windows Authenticode
|
||||
|
||||
CI 已有 PFX 导入和 `Get-AuthenticodeSignature` 门禁。本机应对齐:
|
||||
|
||||
1. 导入 PFX,把 thumbprint 写入 `tauri.signing.conf.json`(`digestAlgorithm: sha256`,时间戳如 `http://timestamp.digicert.com`)。
|
||||
2. 对 `.exe` / `.msi` 都验 `Status -eq Valid`,不要只签主程序。
|
||||
3. 在一台干净 Windows 上安装:SmartScreen 不应再是「未知发布者」。EV 证书对 SmartScreen 更友好,OV 可能仍有一段时间的声誉积累——如实写,不要标「已通过 SmartScreen」。
|
||||
|
||||
### 5. 自动更新(有公钥、HTTPS、回滚才开)
|
||||
|
||||
架构规则已经写死:没有签名公钥、HTTPS 更新源和回滚策略,更新必须保持关闭。接入顺序:
|
||||
|
||||
1. 生成 minisign 密钥;公钥进 `tauri.conf.json` 的 `plugins.updater.pubkey`;私钥只进 Secrets。
|
||||
2. 依赖 `tauri-plugin-updater`,capabilities 只开 `updater:allow-check` 与 `updater:allow-download-and-install`。
|
||||
3. 构建打开 `createUpdaterArtifacts`,每个安装包旁有 `.sig`。
|
||||
4. 发布时生成 `latest.json`(版本、各平台 URL、签名),放到 HTTPS(Gitee/GitHub Release 附件或静态镜像,建议双 endpoint)。
|
||||
5. 前端「检查更新」:**公钥和 endpoint 未进正式包之前不要画这个入口**。
|
||||
6. 回滚:保留上一份 `latest.json`;更新失败或健康检查失败时指回上一版本;文档写清如何撤回错误版本(覆盖 manifest,而不是删掉用户已装的包)。
|
||||
7. `release.py` 除 `.dmg/.exe/.msi` 外还要上传 `.sig` 与 `latest.json`。
|
||||
|
||||
未完成前,设置页、欢迎页、菜单都不要出现「自动更新」或「已是最新」。
|
||||
|
||||
### 6. 发布工作流补齐(与签名独立,但同一闭环)
|
||||
|
||||
`.github/workflows/tauri-release.yml` 现在只 `upload-artifact`(约 90 天过期),`permissions.contents: read`,不能建 GitHub Release。有凭据并公证之后再改:
|
||||
|
||||
- tag 与现有 Gitee 流程对齐(不要两套版本号)。
|
||||
- `contents: write` 后创建 Release,附 SHA256SUMS、安装包、`.sig`、`latest.json`。
|
||||
- 公证步骤放在「Verify native package」之前或之中;未 staple 不得当正式附件。
|
||||
|
||||
GitHub Release 不是「已公证」的替代;没有 notary/Authenticode 时,Release 也只能标开发包。
|
||||
|
||||
## 产物验证
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ npm run acceptance:full
|
||||
8. models.dev 三个源全部失败时不影响已保存 Provider;部分成功时仍能生成可导入目录。
|
||||
9. 新增 Provider 后测试前“保存”禁用;测试实际发送“你是什么模型?请简短回答。”,期间 settings 与 secrets 均无写入;只有非空成功回答显示 HTTP 200,随后保存才写入加密 Key。
|
||||
10. 切换 Endpoint、模型、协议或 API Key 后“保存”立即重新禁用。
|
||||
11. 每一轮只接受唯一单行命令;默认均衡模式下 safe/low/medium 自动执行、high 先确认;严格模式从 medium 起确认;宽松模式不允许绕过 critical 硬拒绝。需要确认时,对话框打开前和用户取消后 `ssh_exec` 调用次数必须为 0。
|
||||
11. 每一轮只接受唯一单行命令;默认宽松模式下 safe/low/medium 自动执行、high 先确认;严格模式从 medium 起确认;critical 前后端均硬拒绝。需要确认时,对话框打开前和用户取消后 `ssh_exec` 调用次数必须为 0。Agent 发起的 `ssh_exec` 必须带 `fromAgent`。
|
||||
12. 确认后只向当前 connectionId 执行;真实输出和 exit code 必须交给下一轮,直到 FINAL 或 8 步上限。
|
||||
13. `rm -rf /`、`mkfs`、对磁盘覆盖的 `dd` 等 critical 命令必须在确认对话框前硬拒绝。
|
||||
14. 相同命令第 3 次必须在执行前拦截;连续失败的下一轮 Prompt 必须要求更换路径。
|
||||
|
||||
+3
-1
@@ -8,6 +8,8 @@ OpsXShell 主打简单好用:常用远程操作走短路径,高级选项默
|
||||
|
||||
需要长期使用时新建保存会话,选择密码或私钥认证,并按需设置分组、标签和启动命令。未填写密码或私钥的导入会话会尝试本机 SSH Agent 和常见默认密钥。
|
||||
|
||||
侧边栏分组内可上下拖拽主机调整顺序。拖到另一分组的标题上会放到该组末尾;分组展开后也可以直接拖到组内某一主机的上方或下方插入。在分组标题右键可选择「按名称排序」一次性重排。顺序会保存,新建的主机排在组末尾;搜索过滤和批量多选模式下暂不可拖拽。
|
||||
|
||||
安装版支持系统链接,例如:
|
||||
|
||||
```text
|
||||
@@ -118,7 +120,7 @@ SFTP 使用双栏文件管理器。中间箭头可上传/下载;上传和下
|
||||
|
||||
- 直接输入任务,例如“排查 nginx 为什么启动失败并修复”。回车发送,`Shift+回车` 换行;不需要先选“解释 / 生成命令 / 排障 / 执行”。
|
||||
- 有终端选区时会作为初始上下文;没有选区时不抓取整屏,Agent 通过真实 `ssh-exec` 自主取证。
|
||||
- Agent 最多执行 8 步。每步只能准备一条单行命令,界面会显示当前主机、命令和五级风险。默认“均衡”模式仅高风险命令确认;“严格”从中风险开始确认;“宽松”仅保留 critical 硬拒绝,适合隔离测试环境。
|
||||
- Agent 最多执行 8 步。每步只能准备一条单行命令,界面会显示当前主机、命令和五级风险。默认「宽松」仅高风险命令确认;「严格」从中风险开始确认。critical(格式化磁盘、删除根目录等)始终硬拒绝,后端也会再拦一次。
|
||||
- 格式化磁盘、删除根目录等 critical 命令会被硬拒绝,不提供确认放行。相同命令第 3 次会在执行前拦截。
|
||||
- 执行后的真实输出和退出码会回给 AI,用于判断下一步或收敛结论。连续失败时 Agent 会被要求换方法。
|
||||
- 长输出由本地 `analyze_output` 提取错误行并保留首尾;Rust 在发给云模型前做常见敏感信息脱敏。
|
||||
|
||||
Reference in new issue
Block a user