Conversation
There was a problem hiding this comment.
Findings
-
[Major] 静默 fallback 吞掉远程错误,违反“no silent fallbacks”并导致失败不可见,证据
apps/desktop/src/main/ssh-remote.ts:349,apps/desktop/src/main/ssh-remote.ts:483
Suggested fix:} catch (error) { throw new CodesignError( `Failed to scan remote directory ${dirPath}`, ERROR_CODES.SSH_REMOTE_READ_FAILED, { cause: error }, ); } // ... } finally { try { await rm(tempPath, { force: true }); } catch (error) { throw new CodesignError( `Failed to clean temp export file ${tempPath}`, ERROR_CODES.SSH_REMOTE_WRITE_FAILED, { cause: error }, ); } }
-
[Major] 新增 UI 使用硬编码尺寸值(
h-9/px-3),与“every UI value via packages/ui tokens”约束冲突,证据apps/desktop/src/renderer/src/components/RemotePathModal.tsx:118
Suggested fix:className="w-full h-[var(--size-control-md)] px-[var(--space-3)] rounded-[var(--radius-md)] ..."
Summary
- Review mode: initial
- 发现 2 个需要修复的问题;
docs/VISION.md、docs/PRINCIPLES.md在当前仓库中 Not found in repo/docs。 - 残余风险:
ssh-remote的错误路径(目录读取失败、临时文件清理失败)缺少针对性单测。
Testing
- Not run (automation)
open-codesign Bot
| let entries: FileEntry[] = []; | ||
| try { | ||
| entries = await readDirRemote(sftp, dirPath); | ||
| } catch { |
There was a problem hiding this comment.
[Major] 这里直接 catch { return; } 会吞掉远程读取错误,违反项目 No silent fallbacks 约束。建议抛出带上下文的 CodesignError,让 UI/调用方可见失败。
} catch (error) {
throw new CodesignError(
`Failed to scan remote directory ${dirPath}`,
ERROR_CODES.SSH_REMOTE_READ_FAILED,
{ cause: error },
);
}| const body = await readFile(result.path); | ||
| return writeRemoteFile(profileId, remotePath, body); | ||
| } finally { | ||
| await rm(tempPath, { force: true }).catch(() => undefined); |
There was a problem hiding this comment.
[Major] .catch(() => undefined) 会静默吞掉临时文件清理失败,也属于 silent fallback。建议显式上抛上下文错误。
} finally {
try {
await rm(tempPath, { force: true });
} catch (error) {
throw new CodesignError(
`Failed to clean temp export file ${tempPath}`,
ERROR_CODES.SSH_REMOTE_WRITE_FAILED,
{ cause: error },
);
}
}| value={path} | ||
| onChange={(e) => setPath(e.target.value)} | ||
| placeholder="/srv/www/index.html" | ||
| className="w-full h-9 px-3 rounded-[var(--radius-md)] bg-[var(--color-surface)] border border-[var(--color-border)] text-[var(--text-sm)] text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]" |
There was a problem hiding this comment.
[Major] 这里新增了硬编码尺寸(h-9、px-3),与项目“every UI value via packages/ui tokens”约束冲突。建议改为 token 变量。
className="w-full h-[var(--size-control-md)] px-[var(--space-3)] rounded-[var(--radius-md)] ..."- 支持保存并测试 SSH Profile\n- 支持关联远程 design system 与附加远程文件\n- 支持将当前预览 HTML 推送到 SSH 服务器\n- 补充共享类型、IPC、store 与前端入口\n- 调整 Advanced 页面 SSH 区块文案与分界线表现 Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
09ac8d9 to
85e7933
Compare
There was a problem hiding this comment.
Findings
-
[Major] SSH 连接未做 host key 校验,允许中间人伪造主机身份,影响凭证与传输安全,证据
apps/desktop/src/main/ssh-remote.ts:108
Suggested fix:const base: ConnectConfig = { host: profile.host, port: profile.port, username: profile.username, readyTimeout: 10_000, hostHash: 'sha256', hostVerifier: (hashedKey) => { const pinned = profile.hostKeySha256; if (!pinned || hashedKey !== pinned) { throw new CodesignError('SSH host key verification failed', ERROR_CODES.SSH_CONNECT_FAILED); } return true; }, };
-
[Major] 远程设计系统扫描吞掉目录读取异常,违反 no silent fallbacks,失败会被静默忽略并产出不完整结果,证据
apps/desktop/src/main/ssh-remote.ts:349
Suggested fix:try { entries = await readDirRemote(sftp, dirPath); } catch (error) { throw new CodesignError( `Failed to scan remote directory ${dirPath}`, ERROR_CODES.SSH_REMOTE_READ_FAILED, { cause: error }, ); }
-
[Major] 远程设计系统读取未限制单文件大小,
readRemoteFileBuffer在扫描路径上以无限上限读入内存,可能被大文件触发内存/性能退化,证据apps/desktop/src/main/ssh-remote.ts:443
Suggested fix:const MAX_REMOTE_DESIGN_FILE_BYTES = 256_000; // ... content: ( await readRemoteFileBuffer(sftp, file.fullPath, MAX_REMOTE_DESIGN_FILE_BYTES) ).toString('utf8'),
-
[Major] 新增 UI 使用硬编码尺寸(
h-9/px-3),违反“every UI value via packages/ui tokens”硬约束,证据apps/desktop/src/renderer/src/components/RemotePathModal.tsx:102,apps/desktop/src/renderer/src/components/SshProfileModal.tsx:264
Suggested fix:className="w-full h-[var(--size-control-md)] px-[var(--space-3)] rounded-[var(--radius-md)] ..."
Summary
- Review mode: follow-up after new commits
- 本轮发现 4 个需修复问题(2 个安全/鲁棒性,1 个性能与可用性,1 个硬约束违规)。
docs/VISION.md、docs/PRINCIPLES.md:Not found in repo/docs。
Testing
- Not run (automation)
open-codesign Bot
| } | ||
|
|
||
| async function toConnectConfig(profile: ResolvedProfile): Promise<ConnectConfig> { | ||
| const base: ConnectConfig = { |
There was a problem hiding this comment.
[Major] 这里构建 SSH 连接参数时未配置 host key 校验,连接会默认信任远端主机身份,存在 MITM 风险。建议增加 host key pinning(hostHash + hostVerifier)并在不匹配时抛出 SSH_CONNECT_FAILED。
| let entries: FileEntry[] = []; | ||
| try { | ||
| entries = await readDirRemote(sftp, dirPath); | ||
| } catch { |
There was a problem hiding this comment.
[Major] 该 catch 直接 return 会吞掉远程目录读取失败,违反 no silent fallbacks,且会让扫描结果静默不完整。建议把异常包装为 CodesignError(SSH_REMOTE_READ_FAILED) 并向上抛出。
| const files = await Promise.all( | ||
| selected.map(async (file) => ({ | ||
| relativePath: file.relativePath, | ||
| content: (await readRemoteFileBuffer(sftp, file.fullPath)).toString('utf8'), |
There was a problem hiding this comment.
[Major] 扫描设计系统时这里未传 maxBytes,会按默认无限制读取远程文件;大文件可导致内存和响应时间显著劣化。建议为扫描路径设置单文件上限(例如 256KB)。
| const selected = profiles.find((profile) => profile.id === next); | ||
| if (!path && selected?.basePath) setPath(selected.basePath); | ||
| }} | ||
| className="w-full h-9 px-3 rounded-[var(--radius-md)] bg-[var(--color-surface)] border border-[var(--color-border)] text-[var(--text-sm)] text-[var(--color-text-primary)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]" |
There was a problem hiding this comment.
[Major] 新增 class 使用硬编码尺寸 h-9 / px-3,与项目“所有 UI 值必须来自 packages/ui tokens”硬约束冲突。建议改成 token 变量(如 h-[var(--size-control-md)]、px-[var(--space-3)])。
背景
有用户反馈希望支持通过 SSH 连接服务器进行开发。当前很多实际开发场景都在远程机器上完成,因此这次补上围绕 SSH 的远程开发资源接入能力。
这次改了什么
验证
已知限制