附件下载无响应 / download.txt
原生下载不携带 Renderer bearer token;同一个 inline URL 也没有明确下载语义和原文件名。
点击时换 fresh attachment_download_url;JuiceFS 下是 60 秒、单附件、intent-bound capability。
把已完成的身份鉴权转换成窄权限票据,再交给 Web / Electron 原生流式下载。
无需迁移。任意旧附件每次点击都现场拿一张新票据。
MIA-277 / 278 / 279 不是三个互不相干的小洞,而是一条“持久对象引用如何安全交给浏览器原生消费者”的完整链路。MIA-284 Agent 已把 staged 生命周期 / GC 整体移交本方案,一起回归上游最终模型。
每个 Issue 都有自己的症状和验收点,但解决原理共享:数据库只保存稳定对象身份,Server 在授权后按使用意图生成原生消费者可用的访问能力。
原生下载不携带 Renderer bearer token;同一个 inline URL 也没有明确下载语义和原文件名。
点击时换 fresh attachment_download_url;JuiceFS 下是 60 秒、单附件、intent-bound capability。
把已完成的身份鉴权转换成窄权限票据,再交给 Web / Electron 原生流式下载。
无需迁移。任意旧附件每次点击都现场拿一张新票据。
鉴权 URL 让原生图片加载失败;旧 expires_at + sweeper 还可能把头像误判为孤儿并物理删除。
先停 sweeper、expiry 读写/query/config,再盘点四类 owner、修引用、读取时解析头像 URL;安全后清理旧 schema/triggers。
先止住继续损失,再把持久对象身份与浏览器当次访问 URL 分离。
对象仍在即可修;对象已被删除只能用权威 seed asset 恢复或重传。
v0.0.2 止血端点分裂 Web/CLI,额外白名单挡住 GIF,触发器依赖脆弱字符串相等。
回归 ordinary upload;写入 durable reference,读取走 avatar resolver,兼容期后删除专用端点。
上传负责对象身份,读取负责访问适配,生命周期不再靠头像专用补丁。
合法旧对象继续可用;错误引用与 MIA-277 共用同一幂等 repair。
点击任一节点查看责任边界。下载与预览共用授权入口,但使用不同 intent;头像上传与头像显示也不是同一个 URL 生命周期。
“停 Sweeper”是保护操作,不是清库操作;真正的数据变更只有可证明安全的头像引用 repair。JuiceFS 文件不需要搬家。
| 现有数据形态 | 本次操作 | 移动对象? | 结果 |
|---|---|---|---|
| 任意历史普通附件,row/object 存在 | 不迁移;点击时签发 fresh capability | 否 | 可下载,恢复原文件名 |
| 合法 raw avatar reference | 保持不变;读取时 resolver | 否 | 可渲染 |
/api/attachments/{id}/download,row/object 都存在 | 幂等改回 durable reference | 否 | 可渲染;重复执行无副作用 |
| attachment row 或 object 缺失 | 不伪造成功;输出 owner/id/损失类型 | 否 | 权威默认资产恢复或用户重传 |
已有 expires_at 行 | 先停 sweeper,惰性列暂留 | 否 | 不再继续按时间删除 |
| 旧函数 / 触发器 / 索引 / expiry schema | 生产盘点、旧 Server 退出后由本工作流做 Phase 2 cleanup | 否 | 结构清理不阻塞行为修复 |
版本是一份产品交付;闸门是部署和迁移的先后依赖。闸门让失败可以在局部回滚,不代表要让用户升级五次。
产出四项精确统计:expiry 风险集合、其中头像引用、四类 owner 的错误 URL、对应 row 已缺失数量;核对默认助手 seed asset,在生产形状快照演练 repair。
当前交付直接停 staged sweeper,删除 expiry query,停止全部 expiry 读写并移除 TTL 配置;不先做 destructive migration,并验证旧 rows/objects 未被修改。
发布下载 capability、forced disposition、avatar resolver/route;运行幂等 repair。旧鉴权下载端点与专用头像端点暂作兼容/回滚入口。
Web/Desktop 获取 fresh download intent;头像控件和 CLI 回归 ordinary upload,补 GIF。部署顺序是 Server → Web → Desktop,并保留双向版本错位兼容。
覆盖三个 Issue、四类 owner、四端、JuiceFS 与文件类型矩阵。旧 Server 退出且数据闸口通过后,本工作流执行 expiry schema/trigger cleanup;客户端兼容窗口结束后再删旧 route。
三个目标 Issue 自身没有 Agent/Squad run;MIA-284 Agent 确实存在,但交接信明确说明它只做授权与绑定,不再碰生命周期、URL 和头像。
MIA-279:in_progress、urgent、未分配。
MIA-278:in_progress、未分配。
MIA-277:in_progress、分配给 member,不是 Agent。
本方案接受完整移交:负责 staged expires_at、sweeper/query/config、迁移 245 function/triggers、URL、下载、头像与 Phase 2 schema cleanup。MIA-284 只负责移除附件级读授权、移除 Issue 绑定 uploader 条件、增加未绑定 id 告警。
两边唯一共享热点 attachmentRequiresCreatorScope 也已切清:MIA-284 只摘掉授权调用,本方案决定并清理 URL 用途。孤儿 blob 不按时间自动删除,attachment_latest_head 不按同名合并。
不是单测里调用了一次 anchor.click 就算完成;必须在真实 Web / Electron 下载与生产形状数据上证明。
JuiceFS/proxy 下 Web 与 Desktop 可下载 PNG、GIF、Markdown、PDF、binary;大文件不进 JS 内存,Range/206 正常。
保存原文件名,图片明确下载而不是只预览;Desktop 不再得到 download.txt。
旧附件任意时刻点击都能拿新票据;60 秒只让旧票据过期,不让附件过期。
默认广告分析助手在冷启动和旧库升级后都有头像,损失对象使用权威 seed asset 恢复。
agent/user/workspace/squad 头像可显示,GIF 可动;绑定的 Work/Issue 私有图不能借 avatar route 公开。
Gate 1 后没有新的定时删除;repair 只修改 row/object 均存在、证据完备的引用。
新客户端不再调用专用头像端点;旧客户端兼容窗口、支持矩阵与回滚方案均有记录。
Web、Desktop、Mobile Web/PWA 与 shared frontend 的 malformed response / old Server fallback 都通过。
Daemon 协议不变,JuiceFS 不替换。主要变化集中在 Server URL 能力、共享下载 hook、头像读写边界与生命周期止血。
| Layer | 状态 | v0.0.4 后的责任 |
|---|---|---|
| Web | changed | 点击时换 fresh download intent;头像消费统一 resolver 返回值。 |
| Desktop | changed | Renderer 传 fresh URL;既有 Electron native download bridge 继续流式下载,不新增文件名 IPC 真相源。 |
| Mobile Web / PWA | changed | 复用 Web 下载和 native avatar load;没有单独 native app。 |
| Shared frontend | changed | optional schema 字段、统一下载 hook、ordinary avatar upload 与旧 Server fallback。 |
| Server | changed | 授权后 mint capability、forced disposition、avatar resolver/route;移除 sweeper、expiry query/读写/config。 |
| Database | changed · schema/data | 幂等修复 avatar_url;不移动对象;Phase 2 删除 expiry 列/索引、函数与四个触发器。 |
| Daemon / CLI / Runtime | changed · CLI only | daemon/runtime/protocol 不变;CLI 头像回归 ordinary upload 并支持 GIF。 |
| Deployment / external | changed | 保证签名 secret 稳定;保留 JuiceFS,不要求 CloudFront 或更换对象存储。 |
| Cross-cutting | changed | 明确 TTL、不持久化、intent、已安装客户端兼容、回滚与历史数据证据。 |
默认不把三个 Issue 拆成多个产品版本;也不为了在同一天物理删除旧 route 或数据库列,而牺牲已安装 v0.0.2 客户端和历史数据安全。