统一画布快速编辑白名单与入口行为 #140

Merged
kdletters merged 51 commits from fix/quick-edit-whitelist into master 2026-08-12 14:46:25 +08:00
Member
  • 使用白名单控制快速编辑功能的显示

  • 同步浮动工具栏、右键菜单、打开入口和提交门禁

  • 禁用角色动作序列帧(整体)、音频和单个图标(explain: backend reject)的快速编辑

  • 把快速编辑api改为只接受resource Id | asset Id,删除 image_src 参数, 以保证校验

其中包含生产数据迁移。迁移用于清理历史普通图片错误持久化的 assetKind="image",覆盖 asset → project-resource → showcase → canvas 四个作用域,并包含 operator 鉴权、分批 dry-run、批次 SHA-256 绑定 apply、active 结构化画

布迁移摘要同步及最终零残留复核。

- 使用白名单控制快速编辑功能的显示 - 同步浮动工具栏、右键菜单、打开入口和提交门禁 - 禁用角色动作序列帧(整体)、音频和单个图标(explain: backend reject)的快速编辑 - 把快速编辑api改为只接受resource Id | asset Id,删除 image_src 参数, 以保证校验 其中包含生产数据迁移。迁移用于清理历史普通图片错误持久化的 assetKind="image",覆盖 asset → project-resource → showcase → canvas 四个作用域,并包含 operator 鉴权、分批 dry-run、批次 SHA-256 绑定 apply、active 结构化画 > 布迁移摘要同步及最终零残留复核。
k88936 self-assigned this 2026-08-05 20:07:08 +08:00
k88936 added this to the 美术画布 project 2026-08-05 20:07:08 +08:00
kdletters requested changes 2026-08-05 20:58:44 +08:00
Dismissed
kdletters left a comment
Member

请求修改。当前 head 的前端入口与定向测试本身基本一致,但仍有两个合同阻塞项:一是正向白名单只落在前端,后端图片编辑 BFF 仍仅拒绝 icon,角色动作、音频、视频及未知类型可绕过 UI 进入 queue/inline 图片编辑链路;二是 decision-log 把单个拆分图标的支持状态和测试结论写反。另请整理 head 合并提交“合并主分支”的空正文,使其符合中文标题后逐行说明变更的仓库提交规范。当前四组 CI 均已绑定 73608a83 通过;修复并更新 head 后请重新请求 review。

请求修改。当前 head 的前端入口与定向测试本身基本一致,但仍有两个合同阻塞项:一是正向白名单只落在前端,后端图片编辑 BFF 仍仅拒绝 icon,角色动作、音频、视频及未知类型可绕过 UI 进入 queue/inline 图片编辑链路;二是 decision-log 把单个拆分图标的支持状态和测试结论写反。另请整理 head 合并提交“合并主分支”的空正文,使其符合中文标题后逐行说明变更的仓库提交规范。当前四组 CI 均已绑定 73608a83 通过;修复并更新 head 后请重新请求 review。
@@ -6110,0 +6110,4 @@
## 2026-08-04 图片画布快速编辑改用统一正向白名单(2026-08-05 修订)
- 背景:画布生成结果统一显示快速编辑,但部分角色动作 / 序列帧和音频结果会进入不受支持的图片编辑链路;不同入口各自判断时也容易继续漂移。
- 决策:快速编辑只支持普通静态图片、角色图、规范图、完整图标图集、单个拆分图标、UI 设计图、宣发图和视频。角色动作 / 序列帧、音效与背景音乐不支持;新增媒体或素材类型默认不开放。浮动工具栏、图层右键菜单、独立图片菜单、打开面板入口和提交门禁统一调用同一个正向白名单。
Member

[P2] 这里把单个拆分图标的合同和测试结论写反了

本行称“单个拆分图标”支持快速编辑,后面的验证说明也称已覆盖其开放与提交;但当前白名单明确没有 icon,模型测试断言 false,提交工作流也断言直接拒绝,另外两份当前编辑器文档同样写不支持。请将长期 decision log 改为“单个拆分图标不支持”,并同步修正验证描述,避免后续按错误共享记忆反向修改实现。

**[P2] 这里把单个拆分图标的合同和测试结论写反了** 本行称“单个拆分图标”支持快速编辑,后面的验证说明也称已覆盖其开放与提交;但当前白名单明确没有 `icon`,模型测试断言 `false`,提交工作流也断言直接拒绝,另外两份当前编辑器文档同样写不支持。请将长期 decision log 改为“单个拆分图标不支持”,并同步修正验证描述,避免后续按错误共享记忆反向修改实现。
k88936 marked this conversation as resolved
@@ -596,3 +596,2 @@
export function isQuickEditUnsupportedAssetKind(layer: CanvasLayer) {
return layer.assetKind === 'icon';
const QUICK_EDIT_SUPPORTED_MEDIA_TYPES = new Set<CanvasLayer['mediaType']>([
Member

[P1] 后端正向门禁缺失,接口可绕过前端白名单

这里新增的白名单只约束浏览器入口和前端提交函数;后端 ensure_editor_image_edit_asset_kind_allowed 仍对除 icon 外的所有值返回允许,queue 与 inline 两条 /api/editor/images/edits 路径都会继续执行。因此认证用户可直接提交角色动作、音频、视频或未来新增类型,角色动作首帧还可能真实进入图片编辑链路。请把同一正向规则下沉到 api-server,基于目标图层的有效 assetKind + mediaType 做端点级校验,并用表驱动测试覆盖全部现役类型和未知类型;视频快速编辑应只走视频生成接口。

**[P1] 后端正向门禁缺失,接口可绕过前端白名单** 这里新增的白名单只约束浏览器入口和前端提交函数;后端 `ensure_editor_image_edit_asset_kind_allowed` 仍对除 `icon` 外的所有值返回允许,queue 与 inline 两条 `/api/editor/images/edits` 路径都会继续执行。因此认证用户可直接提交角色动作、音频、视频或未来新增类型,角色动作首帧还可能真实进入图片编辑链路。请把同一正向规则下沉到 api-server,基于目标图层的有效 `assetKind + mediaType` 做端点级校验,并用表驱动测试覆盖全部现役类型和未知类型;视频快速编辑应只走视频生成接口。
k88936 marked this conversation as resolved
k88936 force-pushed fix/quick-edit-whitelist from 73608a833d to 73fa39ab19 2026-08-06 10:20:10 +08:00 Compare
kdletters requested changes 2026-08-06 14:15:53 +08:00
Dismissed
kdletters left a comment
Member

请求修改。旧 review 中的目标图层后端正向门禁与 decision-log 单图标合同已经修复,但当前 head 新增了两个功能回归:画布 Agent edit_image 任务会被新白名单拒绝;前端媒体类型与素材类型按两个独立集合判断,会把静态图片 + video 标签误路由到视频生成接口。MVP 文档还保留与新合同相反的角色动作快速编辑表述。另请清理 6ed1cfa0、84df62ea、b4e1fdf7 三个空正文“合并主分支”提交,使提交历史符合中文标题后逐行说明变更的仓库规范。CI run 711 已绑定当前 head 四组通过;修复并更新 head 后请重新请求 review。

请求修改。旧 review 中的目标图层后端正向门禁与 decision-log 单图标合同已经修复,但当前 head 新增了两个功能回归:画布 Agent edit_image 任务会被新白名单拒绝;前端媒体类型与素材类型按两个独立集合判断,会把静态图片 + video 标签误路由到视频生成接口。MVP 文档还保留与新合同相反的角色动作快速编辑表述。另请清理 6ed1cfa0、84df62ea、b4e1fdf7 三个空正文“合并主分支”提交,使提交历史符合中文标题后逐行说明变更的仓库规范。CI run 711 已绑定当前 head 四组通过;修复并更新 head 后请重新请求 review。
@@ -19,6 +19,7 @@
- 鼠标中键拖拽始终平移画布;长按 Space 临时进入抓手模式,松开后恢复原工具。
- 图片拖拽时显示水平 / 垂直吸附参考线,吸附到其它图层、生成占位框或画板的边缘与中心线;当移动元素接近两个同轴元素形成的等距位置时,支持横向或纵向等距吸附。
- 生成资源右上角显示元数据按钮,点击打开独立元数据窗口。图片信息页不展示后端组装后的生图 Prompt,也不提供复制 Prompt;只展示该图片生成时用户在面板里提交的输入快照,包括普通生成提示词、规范表单字段、角色设定、图标素材描述、快速编辑提示词、重绘提示词,以及角色规范 / 常规参考图 / 图标规范 / 编辑参考图等参考图卡片,并提供“复制信息”复制当前可见字段。参考图输入快照只保存 `refType/refId` 行引用,其中 `refType="project-resource"` 指向 `editor_project_resource.resourceId``refType="asset"` 指向 `editor_asset.assetId`;不得把图片 Data URL、普通 URL 或 `objectKey` 写入 `generationInputs.references`。旧数据或上传图片没有输入快照时显示 `-`,禁止回退展示内部 Prompt。
- 快速编辑使用统一正向白名单:只支持普通静态图片、角色图、规范图、完整图标图集、UI 设计图、宣发图和视频;单个拆分图标、角色动作 / 序列帧、音效与背景音乐不支持。浮动工具栏、图层右键菜单、独立图片菜单、打开面板入口和提交门禁必须复用同一白名单,新增媒体或素材类型默认不开放。`/api/editor/images/edits` 的 queue 与 inline 路径还必须基于目标图层的有效 `assetKind + mediaType` 执行后端正向门禁;视频快速编辑只能走视频生成接口,不得进入图片编辑 BFF。下文关于“角色动作素材按当前帧图片快速编辑”的历史表述由本条取代,角色动作只能通过对应的动作生成链路继续编辑。
Member

[P2] 不能只声明旧表述“由本条取代”,应直接消除冲突正文

同一文档后面的第 24 行仍写着“角色动作素材的快速编辑按当前帧图片走图片编辑”,与本行、decision-log 和当前实现的“角色动作只能走动作生成链路”相反。RAG 分块检索时旧句仍可能被单独命中。请直接删除或改正后文旧句,使权威文档只保留一个当前合同。

**[P2] 不能只声明旧表述“由本条取代”,应直接消除冲突正文** 同一文档后面的第 24 行仍写着“角色动作素材的快速编辑按当前帧图片走图片编辑”,与本行、decision-log 和当前实现的“角色动作只能走动作生成链路”相反。RAG 分块检索时旧句仍可能被单独命中。请直接删除或改正后文旧句,使权威文档只保留一个当前合同。
k88936 marked this conversation as resolved
@@ -2918,3 +2947,3 @@
.filter(|value| !value.is_empty())
else {
return ensure_editor_image_edit_asset_kind_allowed(payload.asset_kind.as_deref());
return ensure_editor_image_edit_source_kind_allowed(payload.asset_kind.as_deref(), None);
Member

[P1] 这个 fallback 会把画布 Agent 的 edit_image 任务全部拒绝

画布 Agent 在 editor_agent/tool.rs 构造的同一 EditorImageEditRequest 固定为 projectId=当前项目、targetLayerId=None、assetKind="editor_agent_edit_image"。任务进入 external-generation worker 后会调用 edit_editor_image_for_owner 并命中这里;该内部合成类型不在新正向白名单中,因此任务会直接以“当前素材类型不支持图片快速编辑”失败。请按可信调用来源或真实源资源类型保留 Agent 编辑路径,同时继续对画布快速编辑失败关闭,并增加从 Agent payload 到 worker 执行门禁的回归测试。

**[P1] 这个 fallback 会把画布 Agent 的 edit_image 任务全部拒绝** 画布 Agent 在 editor_agent/tool.rs 构造的同一 EditorImageEditRequest 固定为 projectId=当前项目、targetLayerId=None、assetKind="editor_agent_edit_image"。任务进入 external-generation worker 后会调用 edit_editor_image_for_owner 并命中这里;该内部合成类型不在新正向白名单中,因此任务会直接以“当前素材类型不支持图片快速编辑”失败。请按可信调用来源或真实源资源类型保留 Agent 编辑路径,同时继续对画布快速编辑失败关闭,并增加从 Agent payload 到 worker 执行门禁的回归测试。
k88936 marked this conversation as resolved
@@ -672,0 +685,4 @@
'video',
]);
export function isQuickEditSupportedLayer(layer: CanvasLayer) {
Member

[P1] 两个独立集合会放过非法类型组合并调用错误接口

素材标签菜单允许把任意静态图片改成 assetKind="video"。此时 mediaType="image" 与 assetKind="video" 分别命中两个集合,所以这里返回 true;提交层的 isVideoQuickEditSource 又因 assetKind 为 video,把真实图片当视频上传并走视频生成接口。请改为显式合法组合判断,例如仅在 mediaType="video",或兼容旧数据时 mediaType 缺失且 assetKind 为 video,才采用视频快速编辑,并补充交叉组合测试。

**[P1] 两个独立集合会放过非法类型组合并调用错误接口** 素材标签菜单允许把任意静态图片改成 assetKind="video"。此时 mediaType="image" 与 assetKind="video" 分别命中两个集合,所以这里返回 true;提交层的 isVideoQuickEditSource 又因 assetKind 为 video,把真实图片当视频上传并走视频生成接口。请改为显式合法组合判断,例如仅在 mediaType="video",或兼容旧数据时 mediaType 缺失且 assetKind 为 video,才采用视频快速编辑,并补充交叉组合测试。
Author
Member

类似意见在 #117 里也出现了, 问题在于前端手动调整标签assetkind override在保存时会无条件接受,导致真正的assetkind被篡改, #117 在前后端做了校验

类似意见在 #117 里也[出现了](https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/117#issuecomment-1307), 问题在于前端手动调整标签assetkind override在保存时会无条件接受,导致真正的assetkind被篡改, #117 在前后端做了校验
k88936 marked this conversation as resolved
kdletters requested changes 2026-08-06 18:08:42 +08:00
Dismissed
kdletters left a comment
Member

请求修改。review 133 中的三条功能问题已复核修复,但当前 head 与 live master 仍存在内容冲突,Gitea mergeable=false,本地 merge-tree 也确认冲突位于图片画布编辑器 MVP 文档。请先同步 master 并人工保留双方当前合同,在新 head 上重跑完整 CI。提交历史同时仍包含 908d2afe、a083a762、6ed1cfa0、84df62ea、b4e1fdf7 等空正文 merge commit,请在本次重整历史时一并改为符合“中文标题后逐行说明变更”的提交。当前 CI run 741 的 Repository、Frontend、Backend 已通过,Native shell 仍在运行;冲突解决后的新 head 需要重新验证并重新请求 review。

请求修改。review 133 中的三条功能问题已复核修复,但当前 head 与 live master 仍存在内容冲突,Gitea mergeable=false,本地 merge-tree 也确认冲突位于图片画布编辑器 MVP 文档。请先同步 master 并人工保留双方当前合同,在新 head 上重跑完整 CI。提交历史同时仍包含 908d2afe、a083a762、6ed1cfa0、84df62ea、b4e1fdf7 等空正文 merge commit,请在本次重整历史时一并改为符合“中文标题后逐行说明变更”的提交。当前 CI run 741 的 Repository、Frontend、Backend 已通过,Native shell 仍在运行;冲突解决后的新 head 需要重新验证并重新请求 review。
@@ -19,8 +19,9 @@
- 鼠标中键拖拽始终平移画布;长按 Space 临时进入抓手模式,松开后恢复原工具。
- 图片拖拽时显示水平 / 垂直吸附参考线,吸附到其它图层、生成占位框或画板的边缘与中心线;当移动元素接近两个同轴元素形成的等距位置时,支持横向或纵向等距吸附。
- 生成资源右上角显示元数据按钮,点击打开独立元数据窗口。图片信息页不展示后端组装后的生图 Prompt,也不提供复制 Prompt;只展示该图片生成时用户在面板里提交的输入快照,包括普通生成提示词、规范表单字段、角色设定、图标素材描述、快速编辑提示词、重绘提示词,以及角色规范 / 常规参考图 / 图标规范 / 编辑参考图等参考图卡片,并提供“复制信息”复制当前可见字段。参考图输入快照只保存 `refType/refId` 行引用,其中 `refType="project-resource"` 指向 `editor_project_resource.resourceId``refType="asset"` 指向 `editor_asset.assetId`;不得把图片 Data URL、普通 URL 或 `objectKey` 写入 `generationInputs.references`。旧数据或上传图片没有输入快照时显示 `-`,禁止回退展示内部 Prompt。
- 快速编辑使用统一正向白名单:只支持普通静态图片、角色图、规范图、完整图标图集、UI 设计图、宣发图和视频;单个拆分图标、角色动作 / 序列帧、音效与背景音乐不支持。浮动工具栏、图层右键菜单、独立图片菜单、打开面板入口和提交门禁必须复用同一白名单,新增媒体或素材类型默认不开放。`/api/editor/images/edits` 的 queue 与 inline 路径还必须基于目标图层的有效 `assetKind + mediaType` 执行后端正向门禁;视频快速编辑只能走视频生成接口,不得进入图片编辑 BFF;角色动作只能通过对应的动作生成链路继续编辑。画布 Agent 的 `edit_image` 只接收图片输入,新任务按普通静态图片提交空 `assetKind`,不得再生成 `assetKind="editor_agent_edit_image"`worker 仅对 `dedupeKey` 属于可信 `editor-agent:` 命名空间的历史排队任务把该旧 synthetic 值归一为空,普通请求直接提交旧值仍失败关闭。已持久化项目资源中的该旧值在从真实目标图层解析后按普通静态图片兼容,不把该兼容扩大到客户端请求字段。
Member

[P1] 当前文件与 live master 存在内容冲突,PR 无法合并

当前 base 已推进到 281c84b7,而本分支 merge-base 仍是 a03f13d0;Gitea mergeable=false,本地 merge-tree 也在本文件报 content conflict。请同步最新 master 后人工解决该段冲突,既保留本 PR 的快速编辑、画布 Agent 和角色动作合同,也保留 master 在同一长段落加入的最新编辑器约束;解决后的新 head 必须重新跑完整 CI,不能沿用当前 head 的绿灯。

**[P1] 当前文件与 live master 存在内容冲突,PR 无法合并** 当前 base 已推进到 281c84b7,而本分支 merge-base 仍是 a03f13d0;Gitea mergeable=false,本地 merge-tree 也在本文件报 content conflict。请同步最新 master 后人工解决该段冲突,既保留本 PR 的快速编辑、画布 Agent 和角色动作合同,也保留 master 在同一长段落加入的最新编辑器约束;解决后的新 head 必须重新跑完整 CI,不能沿用当前 head 的绿灯。
k88936 marked this conversation as resolved
k88936 force-pushed fix/quick-edit-whitelist from 908d2afe02 to a85522c015 2026-08-06 19:12:36 +08:00 Compare
Author
Member

空正文 merge commit

空正文 merge commit
kdletters requested changes 2026-08-06 20:44:17 +08:00
Dismissed
kdletters left a comment
Member

请求修改。当前 head 已修复旧 review 中的画布 Agent 编辑路径、前端错误路由、文档冲突和提交正文问题,但后端正向白名单仍未把实际 sourceImageSrc 绑定到被校验的目标图层,调用方可以借允许的目标图层编辑同账号内被禁止类型的来源;门禁还继续把未经归一的请求 assetKind 写入结果。与此同时,这项约束会改变 /api/external/v1/editor/images/edits 的请求语义和 400 条件,权威 OpenAPI 与契约测试没有同步。当前 base 为 9dab1f53,merge-tree 无冲突,当前 head 四组 CI 均通过;请闭合真实来源身份与权威类型,并同步 External v1 契约后重新请求 review。

请求修改。当前 head 已修复旧 review 中的画布 Agent 编辑路径、前端错误路由、文档冲突和提交正文问题,但后端正向白名单仍未把实际 sourceImageSrc 绑定到被校验的目标图层,调用方可以借允许的目标图层编辑同账号内被禁止类型的来源;门禁还继续把未经归一的请求 assetKind 写入结果。与此同时,这项约束会改变 /api/external/v1/editor/images/edits 的请求语义和 400 条件,权威 OpenAPI 与契约测试没有同步。当前 base 为 9dab1f53,merge-tree 无冲突,当前 head 四组 CI 均通过;请闭合真实来源身份与权威类型,并同步 External v1 契约后重新请求 review。
@@ -2868,3 +2867,1 @@
return Ok(());
};
if asset_kind != "icon" {
pub(crate) fn ensure_editor_image_edit_source_kind_allowed(
Member

[P2] External v1 的新请求约束没有同步权威契约

这个正向白名单也在 /api/external/v1/editor/images/edits 入队前执行,已经改变 EditorImageEditRequest.assetKind 的允许值、目标图层解析语义和返回 400 的条件;但 docs/openapi/genarrative-external-v1.openapi.json 仍把 assetKind 定义为任意 string/null,也没有覆盖该允许列表与目标/来源关系的契约测试。请在同一变更中同步 OpenAPI 和对应测试,避免外部 Agent 按当前权威契约提交必然被拒的请求。

**[P2] External v1 的新请求约束没有同步权威契约** 这个正向白名单也在 `/api/external/v1/editor/images/edits` 入队前执行,已经改变 `EditorImageEditRequest.assetKind` 的允许值、目标图层解析语义和返回 400 的条件;但 `docs/openapi/genarrative-external-v1.openapi.json` 仍把 `assetKind` 定义为任意 string/null,也没有覆盖该允许列表与目标/来源关系的契约测试。请在同一变更中同步 OpenAPI 和对应测试,避免外部 Agent 按当前权威契约提交必然被拒的请求。
k88936 marked this conversation as resolved
@@ -2954,3 +2995,3 @@
.map_err(map_editor_project_error)?;
let project = editor_project_payload_from_record(project);
let asset_kind = resolve_editor_image_edit_target_layer_asset_kind(
let (asset_kind, media_type) = resolve_editor_image_edit_target_layer_source_kind(
Member

[P1] 被校验的目标图层与实际编辑来源没有绑定

这里仅用 targetLayerId 查目标图层的 assetKind + mediaType,但后续真正送给图片模型的是请求中的 sourceImageSrc,两者没有做 resource/objectKey 一致性校验。直接调用者可以选择一个允许的静态目标图层,同时把同账号内角色动作帧等被禁止来源作为 sourceImageSrc,从而通过门禁;后续持久化又继续采用请求里的 assetKind,还能写入与权威目标不一致或未知的类型。请解析目标图层的权威资源,校验 sourceImageSrc/sourceResourceId 与其一致,并把解析出的有效类型返回给入队、执行和结果持久化,而不是只返回 ()

**[P1] 被校验的目标图层与实际编辑来源没有绑定** 这里仅用 `targetLayerId` 查目标图层的 `assetKind + mediaType`,但后续真正送给图片模型的是请求中的 `sourceImageSrc`,两者没有做 resource/objectKey 一致性校验。直接调用者可以选择一个允许的静态目标图层,同时把同账号内角色动作帧等被禁止来源作为 `sourceImageSrc`,从而通过门禁;后续持久化又继续采用请求里的 `assetKind`,还能写入与权威目标不一致或未知的类型。请解析目标图层的权威资源,校验 `sourceImageSrc/sourceResourceId` 与其一致,并把解析出的有效类型返回给入队、执行和结果持久化,而不是只返回 `()`。
k88936 marked this conversation as resolved
Author
Member

把快速编辑api改为只接受resource Id | asset Id,删除 image_src 参数, 以保证校验

把快速编辑api改为只接受resource Id | asset Id,删除 image_src 参数, 以保证校验
k88936 marked the pull request as work in progress 2026-08-07 14:10:18 +08:00
k88936 force-pushed fix/quick-edit-whitelist from 3592658633 to 21209910dd 2026-08-07 14:43:09 +08:00 Compare
k88936 marked the pull request as ready for review 2026-08-07 17:55:45 +08:00
kdletters requested changes 2026-08-07 18:18:17 +08:00
Dismissed
kdletters left a comment
Member

请求修改。当前 head 05641ab1 已不再是标题和正文描述的“快速编辑白名单”补丁:相对 merge-base 的实际差异是 34 个提交、72 个文件、+6789/-2341,主体为图标规范与图标图集生成重构。请恢复 PR 140 到原任务,或为当前图标规范变更另开 PR 并重写标题/正文;旧 head 上的 reviews 128、133、140、142 不能作为当前差异的审查记录。

当前差异还原地破坏了 External v1 兼容性:图标图集请求删除原必填 referenceImageSrc,替换为必填且 ID-only 的 referenceId,但路径仍是 /api/external/v1、OpenAPI info.version 仍为 1.0.0。仓库权威兼容策略明确把新增请求必填字段和收紧既有字段语义视为 breaking,不能只同步 OpenAPI/Skill;请保留 v1 兼容字段并走弃用流程,或新增 v2 并冻结 v1。

最后,live master 已前进到 6c53eda7,Gitea mergeable=false,本地 merge-tree 确认 editor_project.rs 与 external_generation_worker.rs 存在内容冲突。CI run 797 虽四组通过并绑定 05641ab1,但发生在 master 前进前;解决冲突并更新 head 后必须重新跑完整 CI,再重新请求 review。

请求修改。当前 head 05641ab1 已不再是标题和正文描述的“快速编辑白名单”补丁:相对 merge-base 的实际差异是 34 个提交、72 个文件、+6789/-2341,主体为图标规范与图标图集生成重构。请恢复 PR 140 到原任务,或为当前图标规范变更另开 PR 并重写标题/正文;旧 head 上的 reviews 128、133、140、142 不能作为当前差异的审查记录。 当前差异还原地破坏了 External v1 兼容性:图标图集请求删除原必填 referenceImageSrc,替换为必填且 ID-only 的 referenceId,但路径仍是 /api/external/v1、OpenAPI info.version 仍为 1.0.0。仓库权威兼容策略明确把新增请求必填字段和收紧既有字段语义视为 breaking,不能只同步 OpenAPI/Skill;请保留 v1 兼容字段并走弃用流程,或新增 v2 并冻结 v1。 最后,live master 已前进到 6c53eda7,Gitea mergeable=false,本地 merge-tree 确认 editor_project.rs 与 external_generation_worker.rs 存在内容冲突。CI run 797 虽四组通过并绑定 05641ab1,但发生在 master 前进前;解决冲突并更新 head 后必须重新跑完整 CI,再重新请求 review。
@@ -3539,3 +3539,3 @@
"type": "object",
"required": [
"referenceImageSrc",
"referenceId",
Member

[P1] 不要在 External v1 中直接替换现有必填字段。基线契约这里要求 referenceImageSrc;当前改为必填 referenceId,并把语义收紧为只接受已登记的 icon-spec ID,而路径仍是 /api/external/v1、info.version 仍为 1.0.0。docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md:161-168 明确把新增请求必填字段、收紧语义定义为 breaking,且仅更新 OpenAPI 不构成合规流程。现有 OpenAPI 客户端、Python Skill 调用和 MCP tool 参数都会直接失效。请保留 v1 字段并标记弃用,或新增 v2 并冻结 v1。

[P1] 不要在 External v1 中直接替换现有必填字段。基线契约这里要求 referenceImageSrc;当前改为必填 referenceId,并把语义收紧为只接受已登记的 icon-spec ID,而路径仍是 /api/external/v1、info.version 仍为 1.0.0。`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md:161-168` 明确把新增请求必填字段、收紧语义定义为 breaking,且仅更新 OpenAPI 不构成合规流程。现有 OpenAPI 客户端、Python Skill 调用和 MCP tool 参数都会直接失效。请保留 v1 字段并标记弃用,或新增 v2 并冻结 v1。
k88936 marked this conversation as resolved
k88936 added 18 commits 2026-08-07 19:03:20 +08:00
统一画布快速编辑白名单与入口行为
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / Backend tests (pull_request) Failing after 8s
Project CI / Frontend tests (pull_request) Successful in 2m52s
Project CI / Native shell tests (pull_request) Failing after 4m21s
33d557a78b
新增快速编辑正向媒体与素材类型白名单
同步浮动工具栏、右键菜单、打开入口和提交门禁
禁用角色动作、序列帧、音频和单个图标的快速编辑
补齐白名单回归测试并更新编辑器文档
合并主分支
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 3m1s
Project CI / Native shell tests (pull_request) Successful in 13m12s
73fa39ab19
同步主分支资源卡依赖关系与类型分类预览等最新变更
保留并补齐画布快速编辑前后端正向白名单
拒绝图片编辑接口处理单个图标、角色动作、音频、视频及未知类型
修正快速编辑决策记录与现行编辑器文档
补充后端现役类型和未知类型表驱动测试
同步游戏创作编排恢复与进度可观测性修复
同步编辑器生成幂等、参考图契约与手动完美像素入口
同步开发者密钥时间显示修复
保留画布快速编辑正向白名单改动
同步游戏创作条件任务图路由修复
保留画布快速编辑白名单与相关文档变更
同步画布素材导出分片读取修复
保留角色动作等类型的快速编辑限制
删除历史表述取代说明,直接保留统一正向白名单。

将角色动作当前帧图片编辑改为仅通过动作生成链路继续编辑。
以服务端生成的 editor-agent 队列命名空间恢复可信调用来源。

保留普通画布与 External API 基于素材类型的失败关闭门禁。

补充 Agent payload 到 worker 执行门禁的回归测试与合同文档。
同步智能体根任务可观测性修复
保留画布 Agent 图片编辑门禁与文档约束
撤销基于调用来源全面绕过图片编辑素材白名单的实现。

为改用普通图片空素材类型及有限历史兼容恢复基线。
新 Agent 图片编辑任务以空 assetKind 表示普通静态图片。

仅为可信历史 Agent 队列任务归一旧 synthetic 素材类型。

兼容已持久化旧 Agent 图片资源并保持普通请求失败关闭。

补充 Agent payload 到 worker 门禁及历史兼容回归测试。
同步角色动作前端展示、下载、后端数据结构与精选链路修复
保留画布 Agent 图片编辑素材类型约束
整合前后端手动换签组合校验,避免非法类型调用错误接口
合并主分支并同步 BGM 生成优化
Project CI / Repository checks (pull_request) Successful in 1m6s
Project CI / Frontend tests (pull_request) Successful in 3m10s
Project CI / Backend tests (pull_request) Successful in 3m47s
Project CI / Native shell tests (pull_request) Successful in 14m0s
a85522c015
同步 BGM 生成路径、提示词辅助与预设交互优化
解决图片画布编辑器方案文档冲突
保留快速编辑白名单与画布 Agent 图片编辑约束
分别按项目资源 ID 与素材 ID 主键查询并在双表冲突时失败关闭
校验资源归属、对象存储位置与 asset object 所有权
补齐 Spacetime 客户端映射、facade、生成 bindings 与回归测试
将站内与 External v1 图片编辑请求统一为必填 sourceReferenceId
按业务引用解析权威对象和类型并校验目标图层绑定
使用版本化队列快照并在 worker 执行前复核身份与类型漂移
安全迁移历史队列载荷且不再按 objectKey 反查或信任旧 assetKind
让画布 Agent 使用 ImageMetadata.reference_id 并拒绝未登记图片
同步 OpenAPI 400 条件、异步语义与契约测试
优先使用图层 resourceId 并回退正式 sourceAssetId
未登记来源在上传标注图前失败关闭
保持红框标注图为辅助 referenceImageSrcs 而非主来源
移除图片编辑请求中的旧来源和类型字段并补齐工作流测试
调整 Python helper 使用 source_reference_id 并拒绝空业务 ID
说明上传对象必须先登记为项目资源或素材
同步 External Editor skill 的请求示例和安全边界
更新画布快速编辑与红框辅助引用的专题文档
统一 External v1 API 调用方和上传后登记口径
补充业务 ID 窄查询、队列快照复核的决策与踩坑记录
同步图片编辑权威后端契约
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Failing after 1m55s
Project CI / Native shell tests (pull_request) Successful in 12m10s
3592658633
在后端总纲第九条明确 sourceReferenceId 是图片修改主来源例外
记录 API 入队前窄查询、目标绑定与 400 失败关闭条件
记录版本化队列快照、worker 漂移复核和红框辅助引用语义
k88936 force-pushed fix/quick-edit-whitelist from 05641ab19e to 3592658633 2026-08-07 19:03:20 +08:00 Compare
k88936 added 1 commit 2026-08-07 19:29:38 +08:00
合并编辑器生成结果原子提交改动
Project CI / Repository checks (pull_request) Failing after 8s
Project CI / Frontend tests (pull_request) Failing after 2m4s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Native shell tests (pull_request) Failing after 43s
236c018e43
统一图片、视频与音频生成结果的事务提交和幂等重放
补齐改图任务权威来源快照与历史载荷迁移
同步 SpacetimeDB 表、procedure、客户端绑定和架构文档
保留 worker lease 校验、失败退款与紧凑结果契约
k88936 added 2 commits 2026-08-07 20:16:49 +08:00
同步外部 MCP 项目选择与 API 契约修复
同步 Gitea CI 网络稳定性与构建镜像配置
修复快速编辑来源契约测试
Project CI / Repository checks (pull_request) Successful in 1m3s
Project CI / Frontend tests (pull_request) Successful in 3m13s
Project CI / Native shell tests (pull_request) Successful in 14m16s
Project CI / Backend tests (pull_request) Successful in 4m8s
346ebcf8cb
断言快速编辑通过 sourceReferenceId 提交权威业务引用
禁止测试接受已废弃的来源地址和资源字段
k88936 force-pushed fix/quick-edit-whitelist from 63a5d7991b to 346ebcf8cb 2026-08-07 20:16:49 +08:00 Compare
k88936 added 1 commit 2026-08-07 21:08:17 +08:00
合并主分支
Project CI / Repository checks (pull_request) Successful in 59s
Project CI / Backend tests (pull_request) Successful in 3m47s
Project CI / Frontend tests (pull_request) Successful in 2m55s
Project CI / Native shell tests (pull_request) Successful in 14m56s
ce621b399e
处理合并冲突
k88936 requested review from kdletters 2026-08-07 21:48:08 +08:00
k88936 added 1 commit 2026-08-08 11:17:26 +08:00
合并编辑器场景生成与图片编辑契约
Project CI / Repository checks (pull_request) Failing after 8s
Project CI / Frontend tests (pull_request) Failing after 1m58s
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Native shell tests (pull_request) Successful in 16m24s
0fa951dcd1
合并生成目标预检与图片编辑权威来源校验

保留场景生成前端分流与外部 API 契约

同步 Rust facade、后端架构文档和前端提交工作流
k88936 added 1 commit 2026-08-08 11:26:00 +08:00
合并主分支
Project CI / Repository checks (pull_request) Failing after 59s
Project CI / Frontend tests (pull_request) Failing after 2m15s
Project CI / Backend tests (pull_request) Failing after 2m54s
Project CI / Native shell tests (pull_request) Successful in 16m45s
725930e9d3
解决合并冲突
k88936 added 2 commits 2026-08-08 12:20:12 +08:00
补回快速编辑业务引用解析导入
确保非法主来源在生成目标预检前返回400
补齐场景素材快速编辑白名单
Project CI / Repository checks (pull_request) Successful in 1m26s
Project CI / Frontend tests (pull_request) Successful in 3m0s
Project CI / Backend tests (pull_request) Successful in 4m8s
Project CI / Native shell tests (pull_request) Successful in 15m38s
cd78077e95
同步前端与后端场景快速编辑准入
锁定用户素材标签覆盖的双端白名单
补充新增素材类型的快速编辑检查点
更新场景与画布契约文档
k88936 removed review request for kdletters 2026-08-08 12:25:00 +08:00
k88936 requested review from kdletters 2026-08-08 12:25:13 +08:00
kdletters requested changes 2026-08-08 15:06:01 +08:00
Dismissed
kdletters left a comment
Member

请求修改。当前 head 已解决旧 review 中的合并冲突、来源与目标绑定、Agent 调用和提交正文问题,且四项 CI 全绿;但仍有三处当前阻塞:一是前端按覆盖后的素材标签开放快速编辑,而后端先按资源默认类型拒绝,导致 icon 默认资源改标为 scene/spec 后出现可点击但必然 400 的正常 UI 路径;二是本次已加入 scene 的前后端白名单,但 External v1 权威 OpenAPI 仍声明只允许到 ui-design、其他类型返回 400;三是同一 v1 schema 把 sourceImageSrc 替换成新的必填 sourceReferenceId,却没有兼容字段、v2 路径或基于当前线上调用方状态的新豁免决策。请统一标签覆盖语义、同步完整 OpenAPI 白名单,并按现役版本策略处理 breaking change 后重新请求 review。

请求修改。当前 head 已解决旧 review 中的合并冲突、来源与目标绑定、Agent 调用和提交正文问题,且四项 CI 全绿;但仍有三处当前阻塞:一是前端按覆盖后的素材标签开放快速编辑,而后端先按资源默认类型拒绝,导致 `icon` 默认资源改标为 `scene/spec` 后出现可点击但必然 400 的正常 UI 路径;二是本次已加入 `scene` 的前后端白名单,但 External v1 权威 OpenAPI 仍声明只允许到 `ui-design`、其他类型返回 400;三是同一 v1 schema 把 `sourceImageSrc` 替换成新的必填 `sourceReferenceId`,却没有兼容字段、v2 路径或基于当前线上调用方状态的新豁免决策。请统一标签覆盖语义、同步完整 OpenAPI 白名单,并按现役版本策略处理 breaking change 后重新请求 review。
@@ -1088,6 +1088,7 @@
],
"operationId": "editExternalEditorImage",
"summary": "重绘/调整编辑器图片素材",
"description": "主来源只接受当前账号已登记的项目资源 ID 或素材 IDsourceReferenceId);objectKey、URL、Data URL 与 Blob URL 即使归属当前账号也返回 400。服务端从命中的业务记录派生 canonical objectKey、assetObjectId 与权威类型,只允许普通静态图片(类型为 null)、spec、character、icon-spritesheet、icon-spec、publication-material 或 ui-design,其他及未知类型返回 400。提供 targetLayerId 时必须同时提供 projectId,目标图层必须关联有效项目资源;双方都有 assetObjectId 时必须相同,否则回退比较 canonical bucket/objectKey。同一对象的来源默认类型与目标资源默认类型冲突、目标有效类型或媒体类型不允许、来源或目标不存在/越权/缺少对象时均返回 400,任务不会入队。referenceImageSrcs 仍只作为辅助参考图。",
Member

[P1] External v1 允许类型说明漏掉 scene

当前 head 已允许 scene 图片快速编辑,但这里的权威契约仍只列到 ui-design,并明确称其他类型返回 400。依赖 OpenAPI/MCP 的调用方会把实际合法请求判成非法。请把 scene 同步进允许列表,并让契约测试精确校验完整白名单,避免目前只检查若干描述关键词而漏掉枚举漂移。

**[P1] External v1 允许类型说明漏掉 `scene`** 当前 head 已允许 `scene` 图片快速编辑,但这里的权威契约仍只列到 `ui-design`,并明确称其他类型返回 400。依赖 OpenAPI/MCP 的调用方会把实际合法请求判成非法。请把 `scene` 同步进允许列表,并让契约测试精确校验完整白名单,避免目前只检查若干描述关键词而漏掉枚举漂移。
k88936 marked this conversation as resolved
@@ -3458,3 +3459,3 @@
"minLength": 1
},
"sourceImageSrc": {
"sourceReferenceId": {
Member

[P1] 不能在 External v1 中直接替换必填请求字段

本次把既有必填 sourceImageSrc 删除并改成新的必填 sourceReferenceId,严格客户端会立即失败;这正属于现役版本策略列出的 breaking change。文档中的唯一历史豁免只基于 2026-07-31 当时没有外部第三方调用方,不能自动覆盖今天的新改动。请保留并弃用兼容字段、开 /v2,或先用当前线上 API Key/调用证据重新确认豁免仍成立并形成明确的新决策记录;同时修正本 schema 下游仍称 sourceImageSrc 占用 provider 容量的陈旧说明。

**[P1] 不能在 External v1 中直接替换必填请求字段** 本次把既有必填 `sourceImageSrc` 删除并改成新的必填 `sourceReferenceId`,严格客户端会立即失败;这正属于现役版本策略列出的 breaking change。文档中的唯一历史豁免只基于 2026-07-31 当时没有外部第三方调用方,不能自动覆盖今天的新改动。请保留并弃用兼容字段、开 `/v2`,或先用当前线上 API Key/调用证据重新确认豁免仍成立并形成明确的新决策记录;同时修正本 schema 下游仍称 `sourceImageSrc` 占用 provider 容量的陈旧说明。
k88936 marked this conversation as resolved
@@ -676,0 +690,4 @@
'video',
]);
export function isQuickEditSupportedLayer(layer: CanvasLayer) {
Member

[P1] 标签覆盖后前后端快速编辑门禁不一致

这里仅按覆盖后的 layer.assetKind 判断。图片族标签菜单允许把默认类型为 icon 的层改标为 scene/spec,此处会显示并允许快速编辑;但提交仍使用原 resourceId,后端在应用目标层 override 前先按资源默认 assetKind="icon" 拒绝,形成正常 UI 可达但必然返回 400 的路径。请统一双端语义:若默认 icon 永远禁用,前端也必须检查 resourceAssetKind;若同媒体族 override 应生效,后端需按同一有效类型判断。请补“icon 默认类型 + scene/spec override”的端到端测试。

**[P1] 标签覆盖后前后端快速编辑门禁不一致** 这里仅按覆盖后的 `layer.assetKind` 判断。图片族标签菜单允许把默认类型为 `icon` 的层改标为 `scene/spec`,此处会显示并允许快速编辑;但提交仍使用原 `resourceId`,后端在应用目标层 override 前先按资源默认 `assetKind="icon"` 拒绝,形成正常 UI 可达但必然返回 400 的路径。请统一双端语义:若默认 icon 永远禁用,前端也必须检查 `resourceAssetKind`;若同媒体族 override 应生效,后端需按同一有效类型判断。请补“icon 默认类型 + scene/spec override”的端到端测试。
k88936 marked this conversation as resolved
k88936 added 4 commits 2026-08-08 15:51:38 +08:00
后端按目标图层有效素材类型执行快速编辑门禁
补充 icon 默认资源覆盖 scene 和 spec 的前后端回归
同步图片画布与后端数据契约说明
在 External v1 权威契约中加入 scene 有效类型
用 OpenAPI 扩展精确声明完整快速编辑白名单
强化契约测试并同步外部接入文档
确认 2026-08-08 线上仍无外部调用方
明确豁免 sourceImageSrc 到 sourceReferenceId 的 v1 breaking change
修正 provider 容量说明并增加旧字段文案回归
合并主分支
Project CI / Repository checks (pull_request) Successful in 51s
Project CI / Backend tests (pull_request) Successful in 4m20s
Project CI / Frontend tests (pull_request) Successful in 3m20s
Project CI / Native shell tests (pull_request) Successful in 16m28s
fac9cf0f50
解决合并冲突
k88936 added 1 commit 2026-08-08 16:21:07 +08:00
修复游戏创作清单事件测试时序
Project CI / Backend tests (pull_request) Failing after 10s
Project CI / Repository checks (pull_request) Failing after 10s
Project CI / Frontend tests (pull_request) Successful in 3m27s
Project CI / Native shell tests (pull_request) Successful in 15m41s
68e879907a
先等待 manifest 失效事件监听完成后再记录调用基线。
避免把打开项目后的最近项目复检误判为 Runtime 事件重新打开。
k88936 added 2 commits 2026-08-08 17:53:31 +08:00
移除前端CanvasAssetKind中的image并将普通图片统一表示为null。

在API与SpacetimeDB读写边界清理历史image素材类型。

让画布Agent确认改图时生成版本化来源快照载荷且不扩展worker兼容。

补充快速编辑、迁移、入队回归测试并同步架构文档与项目决策。
合并远端主分支更新
Project CI / Repository checks (pull_request) Successful in 1m32s
Project CI / Backend tests (pull_request) Successful in 4m33s
Project CI / Frontend tests (pull_request) Successful in 4m29s
Project CI / Native shell tests (pull_request) Successful in 13m39s
c3e21132c5
同步 AGC 开发端口分配与启动脚本修复
同步 Jenkins 跨任务产物权限修复
同步移动端提示与门禁恢复
解决实时清单测试竞态冲突
k88936 requested review from kdletters 2026-08-08 19:15:39 +08:00
k88936 added 2 commits 2026-08-08 21:58:57 +08:00
同步 origin/master 的音效生成与画布编辑更新
保留图片编辑来源快照并复用统一结果紧凑化逻辑
修正 Agent 音频任务夹具的可信去重键语义
修复图片编辑权威对象身份校验
Project CI / Repository checks (pull_request) Successful in 1m11s
Project CI / Frontend tests (pull_request) Failing after 2m15s
Project CI / Backend tests (pull_request) Successful in 4m40s
Project CI / Native shell tests (pull_request) Successful in 15m28s
186705954a
校验资源与素材记录的assetObjectId必须匹配objectKey对应的权威对象。

保留无ID历史记录的canonical对象路径兼容并对身份冲突失败关闭。

补充回归测试并同步项目决策记录。
k88936 added 2 commits 2026-08-09 01:08:46 +08:00
同步主线图标规范、生成参数恢复与统一画布生成链路

保留快速编辑的权威引用 ID、素材类型门禁与目标对象一致性校验

补齐 SpacetimeDB 引用解析、V2 引用槽位与相关测试门禁
合并最新主分支
Project CI / Repository checks (pull_request) Successful in 1m15s
Project CI / Frontend tests (pull_request) Failing after 2m3s
Project CI / Backend tests (pull_request) Successful in 3m52s
Project CI / Native shell tests (pull_request) Successful in 13m14s
9ba3cda0b4
同步主线持续集成修复、历史 UI 规范兼容与进程会话终止清理
Member

复审当前 head 9ba3cda0b4ac188d93c5b9a7a4f6c62458ec59bf 后,仍有两项需要收口:

  1. ImageCanvasUploadUtils.ts 已把普通图片的持久化 assetKind 改为 undefined,但 useImageCanvasUploadWorkflow.test.tsx 仍要求 assetKind: "image"。这不是单纯的 CI 波动,而是当前实现与既有上传工作流契约不一致;请确认最终语义并同步实现、测试和相关契约。
  2. 当前分支还在持久化层多个创建、修复、像素处理、showcase 与迁移路径中全局执行 "image" → null 规范化,实际范围明显超出“统一画布快速编辑白名单与入口行为”。请至少更新 PR 标题/正文和相关文档,明确迁移范围、兼容语义及验证;更建议把全局迁移拆成独立变更。

完成后请更新 head 并重新请求审查。

复审当前 head `9ba3cda0b4ac188d93c5b9a7a4f6c62458ec59bf` 后,仍有两项需要收口: 1. `ImageCanvasUploadUtils.ts` 已把普通图片的持久化 `assetKind` 改为 `undefined`,但 `useImageCanvasUploadWorkflow.test.tsx` 仍要求 `assetKind: "image"`。这不是单纯的 CI 波动,而是当前实现与既有上传工作流契约不一致;请确认最终语义并同步实现、测试和相关契约。 2. 当前分支还在持久化层多个创建、修复、像素处理、showcase 与迁移路径中全局执行 `"image" → null` 规范化,实际范围明显超出“统一画布快速编辑白名单与入口行为”。请至少更新 PR 标题/正文和相关文档,明确迁移范围、兼容语义及验证;更建议把全局迁移拆成独立变更。 完成后请更新 head 并重新请求审查。
kdletters requested changes 2026-08-09 13:56:14 +08:00
Dismissed
kdletters left a comment
Member

请求修改:请先解决普通图片 assetKind 新语义与上传工作流现有测试/契约不一致的问题;同时明确或拆分当前分支包含的全局 "image" → null 持久化迁移范围。完成后请更新 head 并重新请求审查。

请求修改:请先解决普通图片 `assetKind` 新语义与上传工作流现有测试/契约不一致的问题;同时明确或拆分当前分支包含的全局 `"image" → null` 持久化迁移范围。完成后请更新 head 并重新请求审查。
Author
Member

解释: 在codex审查时发现前端对assetkind: "image" 没有加入到白名单里, 我之前做动作迁移的时候有关注过assetkind的类型, 一般的图片是作为"未知"处理
shotmd-1786262638.jpg

我追踪这个新增的"image":

发现我在把这个表达式重构成switch时(a03f13d0)想当然地加了"image" 而不是原来的undefined

  修改前的逻辑是:

  assetKind:
    mediaType === 'video'
      ? 'video'
      : mediaType === 'audio'
        ? 'sound-effect'
        : undefined

  也就是说,在该提交之前,普通图片确实是 assetKind = undefined/null。a03f13d0 才把它改成了独立 "image" 值。

codex因此在后端也加了这个assetkind

a03f13d0提交没有上线, 不必迁移, 我彻底清理一下

解释: 在codex审查时发现前端对assetkind: "image" 没有加入到白名单里, 我之前做动作迁移的时候有关注过assetkind的类型, 一般的图片是作为"未知"处理 ![shotmd-1786262638.jpg](/attachments/e80220fd-76a3-4322-8f19-82ad5a62e901) 我追踪这个新增的"image": 发现我在把这个表达式重构成switch时(a03f13d0)想当然地加了"image" 而不是原来的undefined ``` 修改前的逻辑是: assetKind: mediaType === 'video' ? 'video' : mediaType === 'audio' ? 'sound-effect' : undefined 也就是说,在该提交之前,普通图片确实是 assetKind = undefined/null。a03f13d0 才把它改成了独立 "image" 值。 ``` codex因此在后端也加了这个assetkind a03f13d0提交没有上线, 不必迁移, 我彻底清理一下
k88936 added 3 commits 2026-08-09 16:44:30 +08:00
合并 origin/master 的 SFX 音效信息页元数据修复。
修复普通图片类型迁移漏改上传工作流断言的问题。

普通静态图片的项目资源与账号素材创建请求统一省略 assetKind。

补充上传回归断言并同步图片画布上传契约文档。
删除普通图片素材类型兼容
Project CI / Repository checks (pull_request) Successful in 1m6s
Project CI / Frontend tests (pull_request) Successful in 2m53s
Project CI / Backend tests (pull_request) Successful in 3m55s
Project CI / Native shell tests (pull_request) Successful in 13m25s
a251d6b325
移除 api-server 和 SpacetimeDB 对错误图片类型值的归一化与迁移逻辑。
恢复上传工作流直接传递可选 assetKind,并删除对应错误夹具与断言。
保留媒体类型与素材类型不得混用的文档约束,删除历史兼容说明。
k88936 added 1 commit 2026-08-10 11:50:35 +08:00
清理线上普通图片错误素材类型
Project CI / Repository checks (pull_request) Successful in 1m10s
Project CI / Frontend tests (pull_request) Successful in 3m1s
Project CI / Backend tests (pull_request) Successful in 4m6s
Project CI / Native shell tests (pull_request) Successful in 13m28s
44604cf82c
新增受权迁移脚本分批清理 assetKind=image 并执行零残留复核。

仅新增 SpacetimeDB 迁移 procedure,不修改 API 和常规 storage 写入语义。

同步 CLI 返回契约、生成绑定、发布制品、运维门禁和数据契约。
Author
Member

迁移脚本 scripts/spacetime-clean-editor-image-asset-kind.mjs

迁移脚本 `scripts/spacetime-clean-editor-image-asset-kind.mjs`
k88936 requested review from kdletters 2026-08-10 14:25:04 +08:00
kdletters requested changes 2026-08-10 14:51:28 +08:00
kdletters left a comment
Member

请求修改(复审 head 44604cf82c0d642a0c5a620125d1d1679211acb9):

  1. [P1] 普通图片 assetKind 清理会改写项目资源、legacy 双份 layout 和结构化图层,但 apply_editor_image_asset_kind_canvas_plan 没有同步更新 active editor_canvas_layout_migrationstructured_layout_sha256、integrity 与 verified revision。迁移完成后,V2 结构化画布下一次保存会被 verify_migration_layout 判定为“结构化数据已漂移”。请同步维护迁移记录,并补充“active structured canvas 清理后仍可正常保存”的回归测试。

  2. [P1] 迁移清零后,登录态 create_editor_project_resource / create_editor_asset 以及 SpacetimeDB storage 仍会原样接受 assetKind="image"。旧页面、滞留请求或直接 API 调用可立即重新制造被废弃值,而快速编辑白名单仍拒绝它。请在 API 与 storage 权威写边界将精确 "image" 归一为 None,或明确失败关闭,并增加写入门禁测试。

  3. [P2] 权威运维文档要求运行 npm run spacetime:editor-image-asset-kind:clean -- ...,但当前 package.json 没有该 script,迁移按文档无法启动。请补齐 npm script,或把权威文档及运维门禁统一到真实可执行的 node scripts/spacetime-clean-editor-image-asset-kind.mjs

当前迁移已具备 operator 鉴权、分批 dry-run、批次哈希绑定和 apply 后零残留复核,方向合理;请修复上述迁移一致性与入口问题后更新 head,并重新请求审查。另请更新 PR 正文,明确当前 59 文件、+3452/-599 中包含的生产数据迁移和维护窗口范围。

请求修改(复审 head `44604cf82c0d642a0c5a620125d1d1679211acb9`): 1. `[P1]` 普通图片 assetKind 清理会改写项目资源、legacy 双份 layout 和结构化图层,但 `apply_editor_image_asset_kind_canvas_plan` 没有同步更新 active `editor_canvas_layout_migration` 的 `structured_layout_sha256`、integrity 与 verified revision。迁移完成后,V2 结构化画布下一次保存会被 `verify_migration_layout` 判定为“结构化数据已漂移”。请同步维护迁移记录,并补充“active structured canvas 清理后仍可正常保存”的回归测试。 2. `[P1]` 迁移清零后,登录态 `create_editor_project_resource` / `create_editor_asset` 以及 SpacetimeDB storage 仍会原样接受 `assetKind="image"`。旧页面、滞留请求或直接 API 调用可立即重新制造被废弃值,而快速编辑白名单仍拒绝它。请在 API 与 storage 权威写边界将精确 `"image"` 归一为 `None`,或明确失败关闭,并增加写入门禁测试。 3. `[P2]` 权威运维文档要求运行 `npm run spacetime:editor-image-asset-kind:clean -- ...`,但当前 `package.json` 没有该 script,迁移按文档无法启动。请补齐 npm script,或把权威文档及运维门禁统一到真实可执行的 `node scripts/spacetime-clean-editor-image-asset-kind.mjs`。 当前迁移已具备 operator 鉴权、分批 dry-run、批次哈希绑定和 apply 后零残留复核,方向合理;请修复上述迁移一致性与入口问题后更新 head,并重新请求审查。另请更新 PR 正文,明确当前 59 文件、`+3452/-599` 中包含的生产数据迁移和维护窗口范围。
k88936 added 2 commits 2026-08-10 17:51:48 +08:00
在 package.json 注册 runbook 使用的 spacetime:editor-image-asset-kind:clean 命令。
修复普通图片类型迁移一致性
Project CI / Repository checks (pull_request) Successful in 1m16s
Project CI / Frontend tests (pull_request) Successful in 2m57s
Project CI / Backend tests (pull_request) Successful in 4m3s
Project CI / Native shell tests (pull_request) Successful in 13m53s
e3c28a1bca
同步 active 结构化画布迁移摘要与完整性记录,保证清理后可继续保存。

在 API 与 SpacetimeDB 权威写入边界将精确 image 归一为空类型。

补充迁移后保存与写入边界回归测试并更新生产迁移契约。
k88936 requested review from kdletters 2026-08-10 18:57:47 +08:00
kdletters requested changes 2026-08-10 20:19:55 +08:00
kdletters left a comment
Member

请求修改。当前 head 已补上普通图片类型迁移命令、创建入口写入归一化和画布迁移摘要刷新,但仍有两处会破坏迁移安全与数据不变量:cleanup 在校验旧 migration 前直接用当前数据重签摘要,能够把既有漂移洗成有效;legacy 画布保存仍能从客户端 layers 中提取 assetKind="image" 并重新写回 project resource。请按行内方案先验证旧凭证再做受控重签,并把普通图片类型归一化下沉到所有持久化写边界后重新请求 review。

请求修改。当前 head 已补上普通图片类型迁移命令、创建入口写入归一化和画布迁移摘要刷新,但仍有两处会破坏迁移安全与数据不变量:cleanup 在校验旧 migration 前直接用当前数据重签摘要,能够把既有漂移洗成有效;legacy 画布保存仍能从客户端 layers 中提取 assetKind="image" 并重新写回 project resource。请按行内方案先验证旧凭证再做受控重签,并把普通图片类型归一化下沉到所有持久化写边界后重新请求 review。
@@ -8358,6 +8400,10 @@ fn normalize_optional(value: Option<String>) -> Option<String> {
.filter(|item| !item.is_empty())
}
fn normalize_editor_persisted_asset_kind(value: Option<String>) -> Option<String> {
Member

[P1] 把 image → None 不变量覆盖到 legacy 画布保存写路径

这个 helper 目前只用于 resource/asset 创建,persist_editor_project_layout_inner → migrate_canvas_layer_asset_metadata → migrate_project_resource_asset_metadata 仍会把客户端 layer 中的 assetKind="image" 写回空的 editor_project_resource.asset_kind。建议在 legacy 字段提取时区分“字段存在”和“归一化结果”:先记录 had_asset_kind,删除字段后对值调用本 helper;即使结果为 None 也要把布局标记为 changed,保证旧字段被移除。同时在 migrate_project_resource_asset_metadata 写表前再次调用本 helper作为持久化边界兜底。请补 save_editor_project_layout_v2 回归:legacy canvas/resource 初始 asset_kind=None,提交含 assetKind="image" 的 layer 后,保存布局不再含该字段且 resource 仍为 None

**[P1] 把 `image → None` 不变量覆盖到 legacy 画布保存写路径** 这个 helper 目前只用于 resource/asset 创建,`persist_editor_project_layout_inner → migrate_canvas_layer_asset_metadata → migrate_project_resource_asset_metadata` 仍会把客户端 layer 中的 `assetKind="image"` 写回空的 `editor_project_resource.asset_kind`。建议在 legacy 字段提取时区分“字段存在”和“归一化结果”:先记录 `had_asset_kind`,删除字段后对值调用本 helper;即使结果为 `None` 也要把布局标记为 changed,保证旧字段被移除。同时在 `migrate_project_resource_asset_metadata` 写表前再次调用本 helper作为持久化边界兜底。请补 `save_editor_project_layout_v2` 回归:legacy canvas/resource 初始 `asset_kind=None`,提交含 `assetKind="image"` 的 layer 后,保存布局不再含该字段且 resource 仍为 `None`。
k88936 marked this conversation as resolved
@@ -12430,0 +13163,4 @@
&resource_asset_kinds,
)?;
let integrity = canvas_layout_integrity(structured_layout_json.as_str())?;
let migration = refresh_editor_image_asset_kind_layout_migration(
Member

[P1] 清理前先验证旧 migration,不能直接用现状重签

这里应把流程改为“校验旧状态 → 计算受控 patch → 写入 → 校验新状态 → 更新摘要”。在任何写入前,按 migration status 对修改前数据执行校验:active 必须同时核对 legacy shadow 的 source hash,以及当前 structured revision/hash/count/resource refs;backfilled 必须核对 legacy 与 structured 两侧仍与原凭证一致且语义等价;rolled_back 必须沿用重复 rollback 的完整复检。只有旧凭证有效且差异仅来自本次删除精确 image 字段时,才允许重算摘要并保留原 status。当前 refresh 后再调用 verify_migration_layout 只是用刚写入的值自证,发现不了既有漂移。请补真实 DB 状态机测试,至少覆盖 active stale 拒绝、backfilled 双侧漂移拒绝、rolled_back 重入拒绝,以及合法 cleanup 后 save/activate/rollback 仍通过。

**[P1] 清理前先验证旧 migration,不能直接用现状重签** 这里应把流程改为“校验旧状态 → 计算受控 patch → 写入 → 校验新状态 → 更新摘要”。在任何写入前,按 migration status 对修改前数据执行校验:`active` 必须同时核对 legacy shadow 的 source hash,以及当前 structured revision/hash/count/resource refs;`backfilled` 必须核对 legacy 与 structured 两侧仍与原凭证一致且语义等价;`rolled_back` 必须沿用重复 rollback 的完整复检。只有旧凭证有效且差异仅来自本次删除精确 `image` 字段时,才允许重算摘要并保留原 status。当前 `refresh` 后再调用 `verify_migration_layout` 只是用刚写入的值自证,发现不了既有漂移。请补真实 DB 状态机测试,至少覆盖 active stale 拒绝、backfilled 双侧漂移拒绝、rolled_back 重入拒绝,以及合法 cleanup 后 save/activate/rollback 仍通过。
k88936 marked this conversation as resolved
k88936 added 1 commit 2026-08-11 10:58:39 +08:00
修复普通图片迁移旧凭证校验
Project CI / Repository checks (pull_request) Failing after 15s
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / Frontend tests (pull_request) Successful in 2m39s
Project CI / Native shell tests (pull_request) Successful in 13m25s
3dccce7dd3
清理前按 active、backfilled、rolled_back 状态验证旧迁移凭证,写后复核新状态再受控重签。

项目资源清零同步维护受影响迁移摘要,并覆盖无显式画布字段的 rolled_back 状态。

legacy 画布保存与项目资源落表统一归一精确 image,补齐状态机回归及运维契约。
k88936 added 1 commit 2026-08-11 11:24:54 +08:00
合并主分支
Project CI / Repository checks (pull_request) Failing after 14s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 3m5s
Project CI / Native shell tests (pull_request) Failing after 10m48s
c4c694ae7a
解决合并冲突
k88936 added 1 commit 2026-08-11 11:34:14 +08:00
合并主分支
Project CI / Repository checks (pull_request) Successful in 49s
Project CI / Frontend tests (pull_request) Successful in 3m15s
Project CI / Backend tests (pull_request) Successful in 4m6s
Project CI / Native shell tests (pull_request) Successful in 14m56s
81b5168d38
解决合并冲突
k88936 requested review from kdletters 2026-08-11 12:02:09 +08:00
kdletters requested changes 2026-08-11 12:24:09 +08:00
kdletters left a comment
Member

请求修改。当前 head 已修复 review 204 中“先重签后校验”和 legacy 保存回写 assetKind=image 的两项问题,且 CI run 971 四组全绿、与 live master 的 merge-tree 无冲突;但生产清理仍有两处失败关闭缺口:结构化 generation-dialog 的权威 dialog_json 没有进入扫描与 patch,能够残留旧值并错误通过最终零残留复核;project-resource 阶段又会静默跳过缺 migration 记录的结构化画布,先清资源再留下不可正常保存的半迁移状态。请把两类权威状态纳入 dry-run、批次 hash、原子 apply 与回归测试后更新 head,再重新请求审查。

请求修改。当前 head 已修复 review 204 中“先重签后校验”和 legacy 保存回写 `assetKind=image` 的两项问题,且 CI run 971 四组全绿、与 live master 的 merge-tree 无冲突;但生产清理仍有两处失败关闭缺口:结构化 generation-dialog 的权威 `dialog_json` 没有进入扫描与 patch,能够残留旧值并错误通过最终零残留复核;`project-resource` 阶段又会静默跳过缺 migration 记录的结构化画布,先清资源再留下不可正常保存的半迁移状态。请把两类权威状态纳入 dry-run、批次 hash、原子 apply 与回归测试后更新 head,再重新请求审查。
@@ -12430,0 +13340,4 @@
};
let structured_layout_json = build_structured_canvas_layout_json(ctx, &canvas)?;
verify_editor_image_asset_kind_cleanup_migration_state_allowing_prior_resource_cleanup(
&canvas,
Member

[P1] 结构化画布缺 migration 时不能直接跳过

同文件的状态校验已经明确把 layout_storage_version=STRUCTURED 且 migration 缺失视为错误,但这里对所有缺记录的 canvas 都直接 continue。若旧值只在 project-resource 行,当前批次会先把资源清空;后续 canvas 扫描又会因没有显式字段命中而直接返回,最终零残留复核可通过,但该结构化画布仍无法正常保存。请只允许 legacy version 0 无记录,对 structured + missing migration 失败关闭,并把该状态绑定进 dry-run/hash/apply 回归,证明资源行不会被修改。

**[P1] 结构化画布缺 migration 时不能直接跳过** 同文件的状态校验已经明确把 `layout_storage_version=STRUCTURED` 且 migration 缺失视为错误,但这里对所有缺记录的 canvas 都直接 `continue`。若旧值只在 project-resource 行,当前批次会先把资源清空;后续 canvas 扫描又会因没有显式字段命中而直接返回,最终零残留复核可通过,但该结构化画布仍无法正常保存。请只允许 legacy version 0 无记录,对 structured + missing migration 失败关闭,并把该状态绑定进 dry-run/hash/apply 回归,证明资源行不会被修改。
k88936 marked this conversation as resolved
@@ -12430,0 +13457,4 @@
.find(&canvas.project_id);
let mut layer_rows = ctx
.db
.editor_canvas_layer()
Member

[P1] 把结构化 generation-dialog 权威副本纳入清理

这里的 canvas plan 只读取 editor_canvas_layer,遗漏了 editor_canvas_generation_dialog.dialog_json。结构化解析会把 generation-dialog 的顶层扩展字段原样存入该列,因此历史 assetKind=image 可以留在权威 structured 副本;当前 apply 只改 legacy JSON 和 layer rows,随后还能用仍含旧值的 structured JSON 重签 migration。下一轮扫描继续不读 dialog rows,最终 matched=0 会误报零残留。请把 dialog rows 纳入扫描、批次 hash 和原子 patch,并补 active 画布回归,证明 rebuilt structured layout 不再残留该字段。

**[P1] 把结构化 generation-dialog 权威副本纳入清理** 这里的 canvas plan 只读取 `editor_canvas_layer`,遗漏了 `editor_canvas_generation_dialog.dialog_json`。结构化解析会把 generation-dialog 的顶层扩展字段原样存入该列,因此历史 `assetKind=image` 可以留在权威 structured 副本;当前 apply 只改 legacy JSON 和 layer rows,随后还能用仍含旧值的 structured JSON 重签 migration。下一轮扫描继续不读 dialog rows,最终 `matched=0` 会误报零残留。请把 dialog rows 纳入扫描、批次 hash 和原子 patch,并补 active 画布回归,证明 rebuilt structured layout 不再残留该字段。
k88936 marked this conversation as resolved
k88936 added 2 commits 2026-08-11 14:24:02 +08:00
将 generation-dialog 权威 JSON 纳入画布清理扫描、批次指纹和原子 patch。

在项目资源清理前阻断缺少 migration 的结构化画布并绑定 blocker 状态。

补充 active 画布、零残留、批次指纹和缺记录门禁回归测试。

同步后端契约、生产运维说明和共享决策记录。
合并主线并修复画布快速编辑冲突
Project CI / Repository checks (pull_request) Failing after 46s
Project CI / Native shell tests (pull_request) Failing after 1m48s
Project CI / Frontend tests (pull_request) Successful in 2m58s
Project CI / Backend tests (pull_request) Successful in 3m49s
2045ac4d4d
合并 Godot 项目导入与 AGC 原生 HTTP 能力。
保留图片快速编辑业务 ID 契约并移除退役 redraw 分支。
同步共享决策、画布文档与回归测试。
k88936 added 1 commit 2026-08-11 15:04:28 +08:00
合并主分支
Project CI / Repository checks (pull_request) Successful in 1m15s
Project CI / Frontend tests (pull_request) Successful in 2m59s
Project CI / Backend tests (pull_request) Successful in 4m3s
Project CI / Native shell tests (pull_request) Successful in 13m45s
f80427dc45
解决合并冲突
k88936 requested review from kdletters 2026-08-11 15:31:37 +08:00
kdletters added 2 commits 2026-08-12 14:44:42 +08:00
同步主分支的共享画布、游戏创作资源编辑与完美像素合同。\n保留图片快速编辑业务引用、正向白名单与任务快照门禁。\n修复共享画布普通图片类型、完美像素幂等和游戏创作特例融合回归。\n合并后端契约与项目决策记录,并通过本地完整 CI。
Merge remote-tracking branch 'origin/master' into codex/pr140-master-sync
Project CI / Repository checks (pull_request) Successful in 1m33s
Project CI / Frontend tests (pull_request) Successful in 3m24s
Project CI / Backend tests (pull_request) Successful in 4m43s
Project CI / Native shell tests (pull_request) Successful in 16m26s
8302b18dea
kdletters merged commit 8abeb333bb into master 2026-08-12 14:46:25 +08:00
kdletters deleted branch fix/quick-edit-whitelist 2026-08-12 14:46:25 +08:00
Sign in to join this conversation.