修复普通图片迁移旧凭证校验
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

清理前按 active、backfilled、rolled_back 状态验证旧迁移凭证,写后复核新状态再受控重签。

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

legacy 画布保存与项目资源落表统一归一精确 image,补齐状态机回归及运维契约。
This commit is contained in:
2026-08-11 10:52:04 +08:00
parent e3c28a1bca
commit 3dccce7dd3
4 changed files with 1039 additions and 107 deletions
@@ -6921,4 +6921,5 @@
## 2026-08-10 普通图片废弃 assetKind 的迁移与写入门禁
- 语义:普通静态图片的持久化 `asset_kind``NULL`,旧值 `image` 不再是合法业务类型。登录态 API 和 SpacetimeDB storage 的项目资源 / 账号素材创建边界统一将 trim 后精确等于 `image` 的输入归一为空;其它值不借本次迁移扩大或收紧既有校验。
- 迁移:生产维护窗口内按 `asset → project-resource → showcase → canvas` 执行受 operator 鉴权、分批 dry-run、批次 SHA-256 绑定和 apply 后零残留复核的清理。active 结构化画布同步刷新 legacy / structured hash、完整性和 verified revision,但不推进业务 revision、不改 migration 状态或时间戳;缺失一致 active 迁移记录时整批失败关闭
- 迁移:生产维护窗口内按 `asset → project-resource → showcase → canvas` 执行受 operator 鉴权、分批 dry-run、批次 SHA-256 绑定和 apply 后零残留复核的清理。project-resource 清行前验证同工程迁移并把状态纳入批次 hash;清行后能保持原 status 不变量时立即重签,从而覆盖 rolled_back 布局没有显式字段、摘要却依赖资源旧值的情况,仍需显式字段清理的过渡态保留旧凭证。canvas 在写入前再按 active / backfilled / rolled_back 原状态验证旧凭证、双份 legacy shadow、structured revision/hash/integrity 与对应语义等价 / 重入不变量;只有旧凭证有效且差异仅来自受控资源清零及精确 `image` 删除时才写入,写后再用同一状态守卫验证并更新摘要。该过程不推进业务 revision、不改 migration 状态或任何时间戳。旧 migration 摘要中的 `image` 通过清理专用兼容 canonicalizer 复算,正常保存白名单仍拒绝该值
- 持久化边界:除项目资源 / 账号素材创建入口外,legacy 画布保存从 layer 提取 `assetKind` 时必须区分“字段不存在”和“字段存在但归一为 `NULL`”;后者仍删除布局字段并触发持久化。项目资源 metadata 落表前再次归一 stored / incoming 值,防止 legacy V2 保存重新写回 `image`
File diff suppressed because one or more lines are too long
@@ -94,7 +94,7 @@ BgFilter 对已经落入私有 OSS 的生成原图、动作抽取帧和手动去
角色动作正式字段收口使用 `node scripts/spacetime-normalize-editor-character-actions.mjs --database <database> --server-url <url>`,且同样只能由已授权 migration operator 执行。必须先发布包含 normalization cursor 索引和 `normalize_editor_character_animation_metadata_and_return` 的 SpacetimeDB 模块,在 API / worker 仍处于维护模式时先运行默认全量 dry-run;脚本固定按 `asset → project-resource → showcase → canvas` 扫描,普通 scope 每批最多 25 行,canvas 每批最多 5 行。全量 dry-run 会在不写库的情况下把 asset 计划结果投影给同 owner / task / 首帧对象精确匹配的 project-resource,再把前置 scope 的计划结果投影给 canvas 检查;因此同 task 的误标预览 MP4 会先按权威视频对象排除,最终图片序列会逐帧核对并补齐精确 `asset_object` 身份。canvas 中仍引用误标 preview resource 的普通 video layer 会按 project-resource 计划态 `video` 跳过,只有 layout 明确声明动作却指向视频,或资源规划本身失败时才形成 blocker。apply 时仍要求前置 scope 已按顺序物理完成,不能跳过 asset 直接让 project-resource 借未落库结果。历史 canvas 复制的 `sourceResourceId` 不是迁移证据,不要因它仍指向原角色而手工改库,补建资源会采用最终账号素材的 DB 血缘。出现 blocker 时脚本会打印 ID、原因、owner、project、task、对象身份和来源资源;先据此区分最终候选为零 / 多个、正式与旧版冲突、帧对象不匹配或缺失资源,不得跳过 scope。确认 dry-run 后追加 `--apply`,脚本会对每批重新 dry-run、携带该批 SHA-256 apply,并在最后从头要求四个 scope 均为零匹配、零 blocker。只有该复核通过后才发布移除 action fallback 的 API / Web。Stdb build artifact 和完整 release 包必须同时包含 `scripts/spacetime-normalize-editor-character-actions.mjs``scripts/spacetime-migration-common.mjs`。本地切换分支时若要避免 dev publish 因 schema 冲突使用 `-c=on-conflict` 清库,启动命令必须追加 `--preserve-database`,让冲突直接失败。
普通图片错误素材类型清理使用 `npm run spacetime:editor-image-asset-kind:clean -- --database <database> --server-url <url>`,只能由已授权 migration operator 执行。先进入维护模式并发布包含 `clean_editor_image_asset_kind_and_return` 的 SpacetimeDB module,并保持旧版本 API / controller / worker 停止;随后运行默认全量 dry-run,核对 `asset → project-resource → showcase → canvas` 各 scope 的扫描数、命中行数、字段数和 blocker 均符合预期,再追加 `--apply`。脚本对每批重新 dry-run、绑定包含画布迁移摘要的 SHA-256,最后自动从头复核零命中;任一画布数据异常都会只输出哈希化 ID、scope 与原因并停止,不能跳过。清理只处理精确业务旧值,不修改 `asset_object.asset_kind`、MIME 或媒体类型;canvas 清理会在不推进业务 revision、不刷新迁移时间戳的前提下同步 active 结构化画布的 legacy / structured hash、完整性摘要和 verified revision。新版本 APISpacetimeDB storage 的项目资源 / 账号素材创建边界会将 trim 后精确等于 `image``assetKind` 归一为 `NULL`,防止旧页面滞留请求重新制造废弃值。完成零残留复核并确认 active 结构化画布可继续保存后恢复应用版本,最后退出维护。Stdb build artifact 和完整 release 包必须同时包含 `scripts/spacetime-clean-editor-image-asset-kind.mjs``scripts/spacetime-migration-common.mjs`
普通图片错误素材类型清理使用 `npm run spacetime:editor-image-asset-kind:clean -- --database <database> --server-url <url>`,只能由已授权 migration operator 执行。先进入维护模式并发布包含 `clean_editor_image_asset_kind_and_return` 的 SpacetimeDB module,并保持旧版本 API / controller / worker 停止;随后运行默认全量 dry-run,核对 `asset → project-resource → showcase → canvas` 各 scope 的扫描数、命中行数、字段数和 blocker 均符合预期,再追加 `--apply`。脚本对每批重新 dry-run、绑定包含画布迁移摘要的 SHA-256,最后自动从头复核零命中;任一画布数据异常都会只输出哈希化 ID、scope 与原因并停止,不能跳过。清理只处理精确业务旧值,不修改 `asset_object.asset_kind`、MIME 或媒体类型;project-resource scope 在清行前验证同工程 migration 并将其状态纳入批次 hash,清行后能保持原 status 不变量时立即刷新摘要,否则只允许留给后续精确 canvas 字段清理收口。canvas scope 在任何布局写入前再次按 active / backfilled / rolled_back 状态验证原 migration 凭证和双份 legacy / structured 不变量,只允许本批资源清零及精确字段删除造成的差异,写入后再次复核新状态才受控重签摘要,同时保持业务 revision、migration status 与全部时间戳不变。新版本 APISpacetimeDB storage 创建入口、legacy 画布元数据提取和项目资源落表边界会将 trim 后精确等于 `image``assetKind` 归一为 `NULL`,防止旧页面滞留请求或 legacy 保存重新制造废弃值。完成零残留复核,并分别确认 cleaned backfilled 可激活、active 可继续保存、rolled_back 可重复复检后恢复应用版本,最后退出维护。Stdb build artifact 和完整 release 包必须同时包含 `scripts/spacetime-clean-editor-image-asset-kind.mjs``scripts/spacetime-migration-common.mjs`
自 2026-07-11 起,`Genarrative-Full-Build-And-Deploy` 的每日 04:00 timer 默认以 `DEPLOY_TARGET=development``STDB_API_ROLLOUT_MODE=normal` 对仅供开发使用的 dev 服务器执行 Stdb → API → Web 完整发布,不进入人工 rollout gate。三个下游 Build 都由 Full Job 显式传 `PUBLISH_AFTER_BUILD=false`,不得依赖下游 Job 默认值或提前各自发布;统一 Build 完成后仍由 Full Job 按固定顺序发布。人工维护窗口才选择 `pause-after-stdb`,且必须配置 `STDB_API_ROLLOUT_APPROVERS`。上文“定时构建缺少审批人时失败”的旧口径不再作为当前 dev 定时发布行为。
File diff suppressed because it is too large Load Diff