99 lines
3.8 KiB
Markdown
99 lines
3.8 KiB
Markdown
---
|
||
phase: 06-
|
||
reviewed: 2026-04-15T03:54:20Z
|
||
depth: standard
|
||
files_reviewed: 5
|
||
files_reviewed_list:
|
||
- frontend/src/components/workspace/input-box.tsx
|
||
- frontend/src/core/threads/submit-files.ts
|
||
- frontend/src/core/threads/hooks.ts
|
||
- frontend/src/core/threads/hooks.test.ts
|
||
- frontend/tests/e2e/input-and-compose.spec.ts
|
||
findings:
|
||
critical: 0
|
||
warning: 5
|
||
info: 1
|
||
total: 6
|
||
status: issues
|
||
advisory: true
|
||
---
|
||
|
||
# Phase 06: 代码评审报告(聚焦 06-04 gap-closure)
|
||
|
||
**Reviewed:** 2026-04-15T03:54:20Z
|
||
**Depth:** standard
|
||
**Files Reviewed:** 5
|
||
**Status:** issues(建议性、非阻塞)
|
||
|
||
## Summary
|
||
|
||
本次重点审查了 06-04 涉及的输入引用与提交流程。未发现高危安全漏洞,但存在若干会导致行为偏差或可观测性不足的问题:附件仅发送路径被阻断、文件 URL 拉取缺少响应状态校验、上传失败被静默吞掉、缓存更新回调对空数据不安全,以及一个永久 skip 的 E2E 用例导致回归覆盖不足。
|
||
|
||
## Warnings
|
||
|
||
### WR-01: 仅附件消息会被前端拦截,无法提交
|
||
|
||
**File:** `frontend/src/components/workspace/input-box.tsx:297`
|
||
**Issue:** `handleSubmit` 只判断 `message.text` 和 `references`,忽略 `message.files`。当用户仅上传附件而不输入文本时会直接 `return`,与常见聊天上传行为不一致。
|
||
**Fix:**
|
||
```tsx
|
||
if (!message.text && (message.files?.length ?? 0) === 0 && references.length === 0) {
|
||
return;
|
||
}
|
||
```
|
||
|
||
### WR-02: 文件 URL 转 File 时未校验 HTTP 状态,可能上传错误内容
|
||
|
||
**File:** `frontend/src/core/threads/hooks.ts:509`, `frontend/src/core/threads/hooks.ts:723`
|
||
**Issue:** 两处 `fetch(fileUIPart.url)` 后直接 `response.blob()`,未检查 `response.ok`。当 URL 失效返回 404/500 时,错误页面内容也可能被当作文件上传。
|
||
**Fix:**
|
||
```ts
|
||
const response = await fetch(fileUIPart.url);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to fetch file blob: ${response.status}`);
|
||
}
|
||
const blob = await response.blob();
|
||
```
|
||
|
||
### WR-03: `useSubmitThread` 上传失败后继续发送,存在“静默丢附件”
|
||
|
||
**File:** `frontend/src/core/threads/hooks.ts:747-749`
|
||
**Issue:** `useSubmitThread` 中上传失败仅 `console.error`,未 toast、未中断提交,用户会看到消息发送成功但附件未随消息进入上下文。
|
||
**Fix:**
|
||
```ts
|
||
} catch (error) {
|
||
console.error("Failed to upload files:", error);
|
||
toast.error("附件上传失败,请重试。");
|
||
return; // 或 throw error,阻断本次 submit
|
||
}
|
||
```
|
||
|
||
### WR-04: React Query 缓存更新回调假设 `oldData` 非空,存在运行时异常风险
|
||
|
||
**File:** `frontend/src/core/threads/hooks.ts:218-219`, `frontend/src/core/threads/hooks.ts:940-941`
|
||
**Issue:** 两处 `setQueriesData` 回调直接 `oldData.map(...)`;当缓存尚未建立时 `oldData` 可能为 `undefined`,会触发 `TypeError`。
|
||
**Fix:**
|
||
```ts
|
||
(oldData: Array<AgentThread> | undefined) => oldData?.map((t) => { ... }) ?? oldData
|
||
```
|
||
|
||
### WR-05: E2E 用例 DF-INPUT-008 被永久 skip,回归覆盖缺口持续存在
|
||
|
||
**File:** `frontend/tests/e2e/input-and-compose.spec.ts:159`
|
||
**Issue:** `testInfo.skip(true, ...)` 是硬编码永久跳过,导致“stale 引用不阻断发送”的端到端行为无法被自动回归验证。
|
||
**Fix:** 改为条件 skip(基于 fixture 能力探测),或通过 mock/测试路由注入 stale 引用,使该用例在可控环境可执行。
|
||
|
||
## Info
|
||
|
||
### IN-01: 留有 TODO 占位,后续建议纳入工单
|
||
|
||
**File:** `frontend/src/components/workspace/input-box.tsx:662`, `frontend/src/components/workspace/input-box.tsx:1045`
|
||
**Issue:** 仍有连接器/skill 取消能力相关 TODO,表明交互与后端契约尚未完全收敛。
|
||
**Fix:** 将 TODO 关联到明确 issue/phase,避免长期悬置。
|
||
|
||
---
|
||
|
||
_Reviewed: 2026-04-15T03:54:20Z_
|
||
_Reviewer: Claude (gsd-code-reviewer)_
|
||
_Depth: standard_
|