# 技术设计 ## 数据流 ```text 上传接口返回附件元数据 ├─ 普通 composer → submitUserMessage(text, attachments) ├─ 排队 → queueItem.attachments → drain → submitUserMessage └─ 运行中插入 → WebSocket message.attachments ↓ handleMessage 统一解析 ↓ resolvedAttachments(含服务端 path) savedAttachments(无服务端 path) ↓ handleCodexAppSteerMessage ├─ 会话历史保存 savedAttachments ├─ turn/steer 使用 resolvedAttachments └─ stale fallback 使用 resolvedAttachments ``` ## 安全边界 - 前端只发送附件 ID 与公开元数据。 - 服务端通过 `resolveMessageAttachments` 重新读取元数据文件、检查 storageState 与真实文件存在性。 - `localImage.path` 只能来自服务端解析结果。 - 会话 JSON 只保存 `savedAttachments`,不泄露服务端本地路径。 ## 边界情况 - 纯图片:允许;标题/提示回退为图片文件名。 - 部分附件失效:保持现有语义,只发送仍可解析的附件。 - 所有附件失效且无文本:返回既有 `attachment_unavailable`/`empty_message` 错误。 - 删除队列项:清理该项附件,避免孤儿上传。 - stale steer:旧 assistant 输出仍按 timestamp + content 插到已持久化用户消息之前。