PROC-02-014 生态图片全链路审计20261022
图片导入、生成输入、原件落地、预览下载、复用与释放的跨仓代码审计及真实渠道证据
2026-10-22后续方案收敛:用户确认统一URL输入、画布即时预览与自动后台入库、IndexedDB待同步草稿及再次打开恢复。本文整改建议随目标更新,代码观察与两批供应实测保留原时点。当前方案见DEV-X-01-005;本次仅更新文档,没有新增供应调用,多URL同次请求尚未实测。
1. 审计结论
当前复杂度主要来自交互等待、文件身份和持久化职责分散、生成执行与文件读取耦合。单原件、权限隔离、幂等和摘要本身应保留;应减少的是调用方必须理解的保留/交付协议、重复字节搬运和不必要的串行前置。
最直接的交互问题有代码依据:Studio画布先等上传再插入节点;Drama共享画布逐个等待上传再提交节点。两者都会把网络和服务端处理时间加入“添加素材”的等待。延迟上传不需要先等待全部后端重构。
供应输入限制不能只看网关现状。2026-10-21真实供应商测试已确认8个渠道的指定模型可以使用Base64参考图,现有网关却只支持资产ID/HTTPS输入。按用户后续确认,图片和视频参考输入统一URL;本地先预览,后台自动入库,生成仅等待所需文件就绪。Base64支持属于供应能力证据,不再决定产品输入分支。
本报告是全链路架构与代码审计,不是全部线上入口的生产验收。 尚缺匹配现行File Owner的源码/制品确认、浏览器性能基线和部分渠道有效结论;这些缺口在本文单独列明。配套完整方案与实施规格均为Proposed,未改写现行Accepted合同。
2. 方法、证据等级与版本
- C:本次直接读取工作区代码并核对行为;仅证明相应分支存在,未证明线上实际进入该分支。
- L:2026-10-21内联测试见PROC-02-013;2026-10-22另完成URL/混合输入36次真实供应调用并逐张核验,见PROC-02-015。均绕过网关,不等于产品全链路验收。
- D:已接受规范或既有验收记录,注明其时点;不把它当作本次现场运行结果。
- U:缺少现场证据或当前源码,保留待核结论,不推断已经可用。
| 仓库 | 读取时HEAD | 工作区情况与边界 |
|---|---|---|
| Platform | 72787fb706fcc9917d496033abe4a4af57c55d48 | main,干净;不代表生产制品 |
| Runtime | 1e7574015cc1c0eb3679c2d53d4b92a2d1e528b4 | main,干净 |
| Studio | 965d3ccdbe6d505b215a7a2ca2849380276b9de3 | feat/runtime-platform-agent,有未提交改动;审计针对读到的工作区 |
| Drama | c70559025daf0148ad37fa06dd06372c35b5384d | codex/48-drama-direct-test,有未提交改动;分支名不证明对应功能仍在工作区 |
| Media Gateway | 8cdf7079a6db463f5b3ef482f9ba7d9cdeff5a1f | main,干净;与真实渠道测试代码基线相同 |
| Commerce | da1aeaa66e96299ec73dad66f8a8ecb661aea6a0 | main,原型范围 |
| Site | 7af9ff98388a9399a58e5642407017c61f27c2e4 | main;公开静态资产独立处理 |
| Infrastructure | 8dad2f4055b056a1ec5a16e81ff3e28b2990dc5b | main;本次未核验运行中的代理/桶配置 |
| 现用new-api/File Owner | 未取得匹配版本 | 当前项目目录无对应仓库,依据消费者、合同和既有证据,不声称生产方实现已审完 |
32个重点源码文件另存SHA256清单,防止将脏工作区行为错误归因于HEAD提交。清单位于本机任务证据目录的comprehensive-audit-20261022/source-manifest.json;业务代码和其它会话改动未修改。
3. 当前全链路地图
| 环节 | Studio | Drama | Platform / Runtime / 供应层 |
|---|---|---|---|
| 本地导入 | 画布上传后插入;/create已有本地Blob预览、发送时上传 | 共享画布循环上传后插入;产品普通上传进入File Owner | Runtime文件客户端整块Uint8Array;现有Files合同要求摘要与作用域 |
| 输入提交 | 非platform分支使用data URL JSON;platform分支multipart;部分生成入口明确拒绝参考图 | 读取已存文件、校验摘要/MIME,构建Base64 wire输入 | Platform有Base64输入合同与4张/4 MiB/8 MiB限制;MG参考图入口只收资产ID或HTTPS |
| 生成与保存 | 本地代码有结果字节转存及尺寸规范化 | 原件引用进入候选和业务版本;当前direct-test源码需重新定位 | 普通字节输出与原件manifest两条链并存;MG另有spool/transfer/publish |
| 预览与下载 | 产品媒体路由区分下载与处理后预览 | 产品授权后对已引用文件续签/读授权 | 首次manifest可能创建映射/采用;文件读与原操作存在耦合 |
| 复用 | 已有同产品永久storageKey直接复用 | 产品文件、资产版本、画布关联与Runtime引用并存 | file_ref/revision、claim、Artifact、Delivery与业务ID并存 |
| 删除与清理 | 产品有自己的引用计数与媒体清理路径 | 领域引用检查、释放outbox、claim生命周期 | 多消费者保留保护有价值;跨层长期保留和释放协调增加复杂度 |
3.1 用户上传
上图表示已读代码中的两类时序,不代表所有产品共用一个上传入口。未对每层网络耗时做实测,不能把全部等待归因于TOS。
3.2 生成与复用
普通字节链:产品/Runtime → Platform → 供应商 → URL/Base64 → Platform校验/结果保存 → 产品取回字节并保存。
原件引用链:供应输出 → File Owner归档 → Platform原任务/manifest → Runtime采用与送达 → 产品候选/资产/画布。
问题是两个路径同时存在且产品需要理解路径差异。MG自身有另一套临时与输出存储机制,不能仅替换上游地址就宣布达到单原件目标。技术暂存、派生文件、原件备份与另一份业务原件必须分别计数;本报告不把每次暂存都认定为重复原件。
4. Base64使用清单
| 入口/用途 | 已核对路径 | 判断与处理 |
|---|---|---|
| Studio非platform上传 | web/src/services/server-media-storage.ts:38,blobToDataUrl/readAsDataURL | C;整图Base64进入JSON,不应作为默认上传方式 |
| Studio platform上传 | 同文件platform分支使用FormData | C;不是Base64入口,不应一概归类 |
| Studio画布派生、蒙版及旧内容恢复 | use-canvas-node-media-actions.tsx、canvas-page-utils.ts | C;有data URL与后续upload调用,需覆盖裁切、拆图、蒙版及hydrate,不能只改拖入入口 |
| Studio /create附件 | use-create-draft-attachments-store.ts:29、use-create-agent.ts:315 | C;File与object URL先预览、发送时上传,可复用交互模式;未据此证明刷新持久化 |
| Drama生成参考 | apps/web/lib/server/production/reference-media.ts:140–170 | C;文件读回、摘要/MIME校验后toString('base64');目标统一为受权引用解析URL,本地新图先上传就绪,不再保留内联输入分支 |
| Platform参考图合同 | service/platform_media_references.go:18–57 | C;data_base64并进行严格解码;合法协议边界,但无需各层各自复制其快照 |
| Platform普通结果 | service/platform_image_adapter_openai.go:413–647 | C;Base64输出解码、URL下载及再次编码,需与原件登记统一 |
| MG输入 | internal/image/domain/reference.go、两个provider的request.go | C;当前不接受Base64参考输入;不能把输出解析支持当作输入支持 |
| Gemini真实供应协议 | PROC-02-013的inlineData请求 | L;证明该次内联能力,不意味着新目标继续使用Base64输入 |
| OpenAI兼容真实编辑协议 | PROC-02-013的images[].image_url或image字段 | L;Data URL可直接提交给已验证组合;字段因渠道而异 |
需区分三种对象:Base64是字节编码;data URL是携带MIME的内联表示;blob URL是浏览器内的临时句柄。后者不能交给服务端或供应商取图,也不能仅保存该字符串来承诺刷新恢复。
Base64长度为4 × ceil(原始字节数 / 3),另有JSON/前缀成本;约增加三分之一传输字节。压缩率、内存峰值和服务端复制次数另行测量,不能用这个公式直接推导端到端加速比。
5. 问题清单与优先级
供应商字段差异保留为事实;整改建议按用户后续“全部URL、后台入库、本机草稿恢复、不按渠道适配”更新。
以下P1/P2表示本次重构实施优先级,不是安全漏洞定级。没有证据证明当前已发生不可恢复丢失或越权,不虚构P0事故。
| 编号 | 优先级 | 发现、依据与影响 | 推荐处理 / 验收 |
|---|---|---|---|
| A01 | P1 | Studio use-canvas-file-actions.tsx:41等待上传才setNodes;Drama packages/canvas/src/studio/studio-canvas.tsx:879逐张await上传后commit。C | 本地先插入,批量独立预览;在线后台自动上传但不阻塞添加,断网保留草稿并待联网恢复 |
| A02 | P1 | MG输入限制与8个真实支持内联的渠道不一致。C+L | 统一URL作为产品选择;标准协议的单URL与多URL分别核验;无渠道传输开关,不能只测HTTP 200 |
| A03 | P1 | Studio前端 platform-media-tasks.ts:41明确拒绝带references的请求。C | 一并改产品能力投影及请求构造;不能只修MG后宣称前端可用 |
| A04 | P1 | Studio上传20 MiB,Platform单参考4 MiB/合计8 MiB/最多4张,普通输出单张及整批16 MiB;Runtime上传200 MiB,Commerce25 MiB。C | 分离存储能力与生成能力,发布各路径有效限制;合法可存文件不必能被所有模型接受 |
| A05 | P1 | 普通字节路径重复下载/重编码/保存;Drama参考读回后Base64化。C;未量化实际生产频次 | file_id跨层传递;原件在统一上传边界接收,供应端读取受限URL,逐调用测量Put/Copy/传输字节 |
| A06 | P1 | Studio generated-image-normalizer.ts:22存在rotate与cover resize;Commerce参考转RGB/缩至1536,输出重编码PNG。C | 原始结果保持字节;派生明确标注来源和用途;原件下载SHA不变 |
| A07 | P1 | Platform首次manifest在缺映射时可采用原件,且依赖新文件准入;platform_media_files.go:187起。C | 完成结果时登记和交付;下载不执行首次采用;停新后已有已绑定文件仍可读 |
| A08 | P1 | 原件协议检查生成BaseURL等于文件桥BaseURL,既有映射也核对Producer。C | 以稳定Owner身份定位文件;地址变更不改变文件身份,签名与路由仍需授权 |
| A09 | P1 | 平台、Runtime、产品保留与释放相互协调,正常读取/解绑易进入多层恢复。C+D | 产品保留业务权限;Files统一技术保护;Runtime只持执行中/未交付保留。需新职责决策,不能直接删现有保护 |
| A10 | P2 | 文件身份混用storageKey、产品fileId、file_ref、Artifact及Delivery。C | 前端分清local_asset_id与file_id;业务版本保留,技术claim留内部 |
| A11 | P1 | 当前MG Handler请求体上限1 MiB。C;生产代理实际值U | 按上传二进制和生成元数据分别核实有效预算;统一URL后不为内联图片扩大Handler限制,仍需验收真实路径 |
| A12 | P1 | CookingAI/vakv Gemini返回文本Markdown图片;Origin-grok返回200但图像不匹配;本次CookingAI Gemini混合请求遗漏URL素材。L | 响应解析按协议白名单,保留图参有效性证据;不将未知能力或解析失败判为成功 |
| A13 | P2 | 本地草稿在刷新/多标签页/账号切换后的恢复与清理缺统一合同;/create已有预览不等于持久化。C+U | IndexedDB保存待上传Blob和待同步版本;重开查回执并恢复,双端冲突保留草稿,不按TTL丢弃待提交数据 |
| A14 | P1 | 文档目标、脏工作区与实际制品存在核对缺口;当前找不到前次引用的Drama direct-test/client.ts。C+D+U | 固定逐入口Writer/版本清单;历史测试保留其时点,不假设分支名和旧路径等于现状 |
5.1 应保留与应简化的约束
应保留:内容摘要及不可变版本、主体和业务权限、服务凭据隔离、幂等、原任务查询、未知提交不重发、消费者独立保留、真实类型/体积/像素校验、外部URL安全读取。
应简化:添加素材前必须上传、每个入口独立造文件身份、普通下载依赖原生成恢复、已存素材复用先下载再上传、每层长期保存Base64、用供应域名当文件身份、让产品显式选择原件交付协议。
不能把“上传变简单”实现成无限请求体、跨租户哈希取图、关闭校验、丢弃恢复输入或重复收费生成。
6. 真实供应商结果摘要
6.1 2026-10-21单图Base64验证
| 结论 | 具体渠道 | 可用协议/失败边界 |
|---|---|---|
| 通过8个 | CookingAI Gemini/GPT/Grok;Origin Gemini/GPT/GPT-4k;vakv Gemini/GPT-cc | Gemini inlineData;Origin/vakv GPT images[].image_url;CookingAI GPT/Grok image字符串 |
| 图参核验未通过1个 | Origin-grok | 两次返回无关图;不证明所有型号及协议都不支持 |
| 无法判断4个 | 两个tuba渠道、两个zdapi渠道 | 连接中断、502、指定模型不可用;不归类为“不支持Base64” |
以上是每渠道单个配置模型、单张合成图片的真实验证,不是该供应商全模型能力认证。Origin-gpt-4k本次输出1024×1024,不构成4K验收。停用渠道仍保持停用。测试费用未对账,连接中断的未知请求未继续重发。详细请求形式、回执、异常与图像核验方法见PROC-02-013。
6.2 2026-10-22已有素材URL与混合输入补测
13个渠道各一个配置模型,36次POST取得36个响应:32次200保存32张图,2次400、2次503;21张图参核验通过、11张未通过。完整请求矩阵、字段与图像证据见PROC-02-015。
| 结果组 | 已有素材URL | 同次URL+Base64 | 对统一协议的含义 |
|---|---|---|---|
| Origin Gemini/GPT/GPT-4k、两个tuba、vakv Gemini/GPT-cc、zdapi GPT Image 2,共8个 | 通过 | 通过 | 方案选定字段下两项均通过 |
| CookingAI GPT/Grok,共2个 | 补充image字符串通过 | 补充image字符串数组通过 | 能力存在,但现定images[].image_url基线不兼容;不新增渠道特例 |
| CookingAI Gemini | 通过 | 200但只复现Base64素材,遗漏URL素材 | 单URL成功不能证明混合可靠 |
| Origin-grok | 未通过 | 未通过 | 6次不同字段测试均返回无关图,不将200记为成功 |
| zdapi GPT Image 2.5 | 无法判断 | 无法判断 | 503 model_not_found,非传输能力结论 |
含补充字段的能力结论为URL确认11/13、混合确认10/13;统一字段两项均通过8/13。使用自有合成图和私有TOS签名URL,匿名读取403;测试完成已删除唯一测试对象并确认HEAD 404。未用客户素材、未改渠道启停、未部署业务代码。
7. 性能判断
| 用户操作 | 可由结构推导的改善 | 尚不能承诺 |
|---|---|---|
| 添加画布素材 | 本地显示移出网络关键路径,不等上传/保存/回读 | 大图解码仍可能慢,不能保证所有设备瞬间完成 |
| 第一次生成 | 后台上传可与用户编辑重叠,生成只等本次尚未就绪的依赖 | 新图仍需上行并取得URL;未完成上传仍要等,带宽和供应生成耗时不因此消失 |
| 同素材再次生成 | 复用受权file_id,浏览器不重复传相同字节 | 供应端仍需取图;URL复用不等于整个系统零I/O |
| 预览/加载 | 按展示尺寸读取派生图,合并授权续签,避免普通读取走任务恢复 | 缓存冷启动、派生尚未就绪和弱网仍需测量 |
| 原件下载 | 更短的授权路径,授权后直接读取对象 | 不承诺原文件体积变小;原件不可为提速被静默裁切 |
已补URL/混合输入的功能验证,但仍没有同模型、同输入、同参数的严格性能对照,以及端到端瀑布图、p50/p95、内存峰值与TOS I/O基线。所有时间收益仍是设计假设;不把两批异构供应测试耗时混成速度排名。
8. 逐仓整改落点
| 仓库/模块 | 首先处理 | 保留边界 |
|---|---|---|
| Studio | 画布全部导入与派生入口、本地草稿;解除产品参考图能力断层;停止原件转存与静默cover | 对话/素材/画布权限和独立发布权限 |
| Drama / packages/canvas | insertFiles先节点后提交;Host补输入准备能力;更新参考图构造;候选/资产/画布引用统一 | 业务版本、采纳与项目权限;direct-test例外不扩成生产绕过 |
| Media Gateway | 图片/视频统一URL、标准编辑协议、单/多URL验证、输出包装解析与有效预算 | 选路、容量、健康、Attempt和未知状态保护;不自动启用渠道 |
| Platform | 输入身份/能力、Operation快照、文件登记与首次交付;读取脱离重复原账恢复 | 唯一钱包、授权、计费及已确认原单 |
| Runtime | 文件客户端独立于编排;执行输入/输出引用和可靠送达;已交付长期文件保留职责收敛 | Job、Artifact追踪和执行中保护 |
| File Owner / Infrastructure | 流式接收、上传回执、统一身份和文件生命周期、读授权、派生和观测 | 复用既有TOS,唯一物理内容权威;不新增第二Writer |
| Commerce | 记录未来接入点与原型派生语义 | 不据本审计启动冻结范围外产品建设 |
| Site | 仅处理显式发布的素材与派生 | 公开静态资产不套私有任务读取链,不合并公开/私有桶 |
8.1 云配置只读补充
2026-10-22已通过控制台核对实际7桶,详见PROC-02-016。assets无桶生命周期,media启用全桶最后修改7天删除;MG三桶没有桶生命周期和CORS。现用assets/media CORS仅4个旧Origin,需按实际浏览器入口验证,不能推断已证明全部卡顿原因。
用户已接受三类用途分工、最终位置直接写入、原件/预览分工、普通读取简化和异步释放。清单保留历史对象与测试隔离,后续MG新链取消replica强制配置及同步写入等待;本轮云端写入、对象上传删除、生产部署均0。
9. 未闭合项与实施前证据
后续核对已取得实际运行revision及对应File Owner原件分支,见PROC-02-017。下列第1项的制品/源码缺口已部分补齐,仍需逐入口验证;本报告前文保留早先审计时点。用户随后选择独立实例与全新桶,旧桶复用不再作为执行方向,最新范围以DEV-X-01-006第7.2~7.4节为准。
- File Owner:取得实际运行制品、对应源码、既有对象身份与写入Owner;确认上传就绪和业务登记能复用同一原件而不复制对象。
- Studio:逐入口核对运行模式、部署版本及真实Writer,不能把工作区与共享原件接入规范任选一个当成线上事实。
- Drama:当前direct-test路径已与前次记录不同,先定位当前接线和范围;本次不改动正在进行的工作区重构。
- 供应能力:多URL同次请求尚未验证;未验证组合保持unknown;单独区分“协议支持”“当前可用”“管理员启用”,不新增强制运营启用门禁。
- 性能与边缘:补实际反向代理/BFF/请求体限制、签名有效期、CORS/Range、缩略图缓存、CPU/RSS和网络基线。
- 用户语义:后台自动同步、本机草稿范围与重开规则已确认并写入共享原件PRD及实施规格;跨产品分享与来源撤销后目标引用仍需规格化,保持原权限范围。
“完整”表示覆盖从导入到删除的生态问题、责任、证据和未闭合项,不代表这些缺口已凭文档消失。审计发现如何落地、如何验证,按配套方案与实施规格执行。