服务端配合修改清单:聊天附件(移动端)

面向 DeepTutor 服务端的配合需求 · 提交方:移动端 v1.1.0
状态 已完成P0 2/2P1 1/1实施 HMS 服务端基线 v1.5.16 (8515dfd)

现状确认无需改动

移动端按上游契约发送,服务端已正常工作(本次复核确认):

POST /api/v1/partners/{partner_id}/chat/execute-stream
{
  "content": "…",
  "session_key": "app-xxx",
  "attachments": [
    { "type": "image", "base64": "…", "filename": "a.png", "mime_type": "image/png", "url": "" }
  ]
}

P0-1:附件下载端点已实施

新增端点(与建议形态一致,id 采用哈希反查而非路径拼接,结构性免疫路径穿越):

GET /api/v1/partners/{partner_id}/attachments/{attachment_id}
鉴权: router 级 admin 依赖(与全部伙伴 API 一致)
attachment_id: 12 位十六进制 = sha1(文件绝对路径)[:12](与 history 中的 id 同源)

实测:

用例结果
带 Bearer 下载 4MB PDF200 · md5 与服务端文件一致
Content-Dispositionattachment · 前缀已剥 · RFC5987 UTF-8(中文「勺嘴鹬.png」正常)
无 token401
伪造 / 他人 partner 的 id404(admin-gated,无越权面)
不存在404
../ 穿越尝试404(id 仅做哈希匹配,不参与路径构造;非 12hex 直接 400)

P0-2:history 附件安全化已实施

history 响应中的附件记录现在长这样(实测,与建议字段完全一致):

{
  "id": "f46731c5dce4",
  "type": "pdf",
  "filename": "2000_Core_Words.pdf",      ← uuid12_ 前缀已剥离
  "mime_type": "application/pdf",
  "size": 4083819,
  "download_url": "/api/v1/partners/dina/attachments/f46731c5dce4"
}
超额完成:响应体积
排查发现 36MB 的真正大头是 events 工具轨迹(find/grep 完整输出,单条消息可达 6MB)。新增 ?include_events=false 瘦身参数(默认 true 保持 Web 端活动面板兼容):实测 41.5MB → 55KB(约 750×)。移动端拉历史时请带上该参数。

P1-1:流式首帧 / 心跳已实施

可选项未实施 · 记录在案

  1. 单条消息删除/撤回:暂缓——需动 JSONL 存储层,收益有限;当前以测试专用 session_key + 整会话删除管理测试污染
  2. 附件配额与清理:暂缓——media/ 目前 5 个测试 PNG + 2 个真实文件,量级可忽略;达到 GB 级再做按 partner 配额

服务端验收清单(原始项逐条核对)

移动端对接速查

变更对接方式
附件下载GET /api/v1/partners/{pid}/attachments/{id}(id 从 history 的 download_url 直取)
瘦身历史GET .../history?include_events=false
心跳解析 SSE 时忽略 event: ping 但重置空闲计时器