统一 AGC 项目与发行版本模型
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m18s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 3m54s
Project CI / Frontend tests (pull_request) Failing after 1m28s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m33s
Project CI / Repository checks (pull_request) Failing after 1m15s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m15s
Project CI / Backend tests (pull_request) Successful in 6m50s
Project CI / Native shell tests (pull_request) Successful in 6m45s

将用户版本改为可回退、可重复提交的版本标签,使用不可变 versionId 区分具体提交实例。

明确 publicationRevision 仅负责并发 CAS,不再限制用户版本号递增。
This commit is contained in:
2026-10-03 15:45:12 +08:00
parent 1621c29cf0
commit 996135379b
3 changed files with 27 additions and 31 deletions
@@ -8,21 +8,21 @@
## 修改边界
- `packages/shared/src/contracts/gameCreationApp.ts`:本地 `publication` 绑定,不混入本地编辑迭代 `versions[]`。
- `packages/shared/src/contracts/gameDistribution.ts` 与 Rust shared-contracts:创建版本请求增加可选 `versionNumber`。
- `apps/ai-game-creator-shell`:绑定回读、首次发布/更新 UI、目标版本输入、原 gameId 新版本发布、结果回写。
- `api-server`、`spacetime-client`、`spacetime-module`:把可选目标版本号传入现有创建版本 procedure,事务内比较最大版本号并拒绝冲突。
- `packages/shared/src/contracts/gameCreationApp.ts`:本地唯一 `projectVersion` 和 `publication` 绑定,不混入内部编辑迭代 `versions[]`。
- `packages/shared/src/contracts/gameDistribution.ts` 与 Rust shared-contracts:创建版本请求支持正整数 `versionNumber`,允许重复标签提交。
- `apps/ai-game-creator-shell`:绑定回读、首次发布/更新 UI、项目版本输入、原 gameId 新提交、结果回写。
- `api-server`、`spacetime-client`、`spacetime-module`:创建版本事务只校验正整数;同 gameId/同 versionNumber 生成新 versionId,publicationRevision 继续 CAS。
- 现有创建版本 procedure 输入/生成绑定需要同步,但不修改持久表字段。
## 实现顺序
1. 契约先补 `versionNumber?: number` 和本地 `publication`,明确版本号校验与兼容。
2. 创建版本事务在未传时自动递增;传入时必须大于现有最大版本号,并在同事务内校验。
3. AGC 发布绑定保存 `gameId`、最新版本、状态和 revision;按账号和 API origin 隔离绑定。
4. AGC 打开项目回读已有作品;旧项目通过 `localProjectId` 恢复关联。
5. 发布面板区分首次发布/更新,给出当前版本和可编辑目标版本输入。
6. Rust 发布 facade 在更新模式跳过创建 game,使用原 gameId 创建新 version;幂等账本把目标版本号纳入发布意图,不能仅以 ZIP 摘要合并不同发布。
7. 验证重复提交、响应丢失、切换账号、版本冲突、旧作品恢复,以及旧公开版本在新版本审核中继续可玩。
1. 契约先补唯一 `projectVersion` 和本地 publication,明确 versionId/版本标签/内部 projectRevision 的边界。
2. 创建版本事务不再要求大于 max;未传时保留旧客户端自动递增,传入时校验正整数,并按同版本最新有效提交处理 pending 替代。
3. AGC 发布绑定保存 gameId、最新 versionId、状态和 revision;按账号和 API origin 隔离绑定。
4. AGC 打开项目回读已有作品;旧项目通过 localProjectId 恢复关联。
5. 发布面板编辑 projectVersion,区分首次发布/更新,允许重复提交和回退,不再存在独立 targetVersion。
6. Rust 发布 facade 在更新模式跳过 create game,使用原 gameId 创建新 version;幂等账本把目标 projectVersion、资料和提交意图纳入发布意图。
7. 验证重复提交同版本、回退版本、响应丢失、切换账号、publicationRevision 冲突和旧公开版本继续可玩。
## 数据库影响
@@ -9,21 +9,13 @@
## 目标
让 AGC 区分首次发布与已有作品更新:已有作品继续使用原 `gameId`,创建不可覆盖的新版本;发布时用户可以决定目标正整数版本号。
## 范围
- 本地项目清单保存平台作品绑定和最近版本状态。
- 打开项目时回读绑定作品;旧清单按 `localProjectId` 做一次性恢复。
- 发布面板显示首次发布/更新模式、当前版本和建议目标版本。
- 用户在发布时填写目标版本号,默认最大版本号加一。
- 服务端可选接收 `versionNumber`;旧客户端不传时继续自动递增。
让 AGC 区分首次发布与已有作品更新:已有作品继续使用原 `gameId`;用户维护唯一项目发行版本标签,同一标签可以重复提交或回退,具体提交由不可变 `versionId` 标识。
- 同一 `gameId` 的新版本上传、校验、送审和结果回写。
## 不在范围内
- AGC 完整版本历史页、版本回滚、版本删除、版本对比。
- 覆盖已有版本号或原地替换发行包。
- AGC 完整版本历史页、版本对比和一键回滚 UI;回退版本标签的发布路径属于本里程碑。
- 原地替换已发布 `versionId`;已发布提交保持不可变。
- 新增 SpacetimeDB 持久表或修改 `game_distribution_version.version_number` 类型。
- 改变公开 URL、审核状态机、发行网关或后台审核权限。
@@ -31,8 +23,11 @@
- [ ] 首次发布完成后项目清单保存 `gameId`、`versionId`、版本号、状态和 `publicationRevision`。
- [ ] 重新打开同一项目显示“更新游戏”,不再显示“创建平台游戏”。
- [ ] 默认目标版本为最大版本号加一,用户可改为更大的正整数。
- [ ] 目标版本不大于已有最大版本号时服务端拒绝,不能覆盖旧版本。
- [ ] 项目清单只有一个用户发行版本字段,发布面板编辑它,不存在独立 targetVersion。
- [ ] 同一 `gameId`、同一 `versionNumber` 可以重复提交,生成新的 `versionId`,不覆盖旧公开实例。
- [ ] 项目版本可以低于线上最新版本,服务端允许回退标签,但仍校验为正整数。
- [ ] 同版本旧 pending 提交被取消或被最新提交替代,审核队列不产生重复有效任务。
- [ ] `publicationRevision` 仍用于并发 CAS,与用户版本号规则独立。
- [ ] 更新使用同一 `gameId`,只增加一个新 `versionId`,公开地址保持不变。
- [ ] 旧项目没有发布绑定时能按作者和 `localProjectId` 恢复;恢复失败时明确回到首次发布。
- [ ] 上传响应丢失、重复提交、版本号冲突和切换账号不会创建重复游戏或错误接管作品。
@@ -94,14 +94,15 @@
### 身份、状态、审核与更新
- `gameId` 是服务端分配的稳定游戏身份;`ownerUserId` 只从当前认证主体派生。AGC 本地 `projectId` 只用于关联提示,不能证明云端游戏所有权。AGC 发布成功后必须把 `gameId`、最近 `versionId`、`versionNumber`、`publicationRevision` 和状态写入项目清单;网页上传和 AGC 发布使用相同游戏、版本与上传记录,不建立两套发行系统。
- 同一作者用相同 `localProjectId` 再次发布时复用既有 `gameId` 并只新增版本;AGC 如果清单缺少发布记录,首次更新前按作者作品回读和 `localProjectId` 做一次性恢复。缺少 `localProjectId` 的旧客户端仍可发布,但会被视为新建游戏。
- 每次发行分配唯一 `versionId`,`version_number` 已存在于版本表。服务端保留“未传版本号时自动取最大值加一”的旧客户端兼容行为;AGC 更新发布必须让用户填写正整数版本号,默认建议为当前最大版本号加一。版本号必须严格大于该游戏已有最大版本号,不能覆盖、重用或静默改写旧版本;允许跳号但发布前明确展示当前版本与目标版本。
- `gameId` 是服务端分配的稳定游戏身份;`ownerUserId` 只从当前认证主体派生。AGC 本地 `projectId` 只用于关联提示,不能证明云端游戏所有权。项目清单保存唯一用户发行版本 `projectVersion`,以及平台 `gameId`、最近 `versionId`、`publicationRevision` 和状态;网页上传和 AGC 发布使用相同游戏、版本与上传记录,不建立两套发行系统。
- 同一作者用相同 `localProjectId` 再次发布时复用既有 `gameId`。一次具体上传/资料/审核快照由不可变 `versionId` 标识;同一个用户版本标签可以有多个提交实例,旧公开实例不原地修改。AGC 如果清单缺少发布记录,首次更新前按作者作品回读和 `localProjectId` 做一次性恢复。
- `projectVersion`/`version_number` 是用户可见的正整数版本标签,不要求严格递增,允许回退和重复提交。AGC 发布面板直接编辑项目清单的 `projectVersion`,不再维护独立 `targetVersion`;服务端不传时保留旧客户端自动取最大值加一的兼容行为,传入时只校验 `versionNumber >= 1`。
- 同一 `gameId` 与同一 `versionNumber` 的再次提交创建新的 `versionId`;旧的 `published`/`activeVersionId` 继续服务,新的提交审核通过后才切换 `activeVersionId`。旧的 pending 提交可被新提交标记为 `cancelled`,审核队列只展示最新有效提交。`publicationRevision` 仍然严格 CAS 递增,但不限制用户版本号。
- 游戏单独保存 `publicationRevision`、`activeVersionId` 和可见性 `unpublished | published | suspended`;正式可见性由服务端持久化事实决定。未通过审核时 `activeVersionId` 为空;`suspended` 是管理员安全下架,作者不能自行解除。
- 版本状态为 `awaiting_upload → uploaded → validating → pending_review → published`。上传确定失败进入 `upload_failed`,验证失败进入 `validation_failed`,人工拒绝进入 `rejected`;尚未公开版本可以撤回为 `cancelled`,已公开版本可撤销为 `revoked`。已成功上传的相同字节可重新校验;内容改变或审核拒绝后的修改必须新建版本。
- 首版建议人工审核。审核员检查游戏资料、真实桌面运行、声明移动适配、内容与外部请求被阻断的行为;自动包校验通过只进入 `pending_review`,不自动公开。审核记录保存审核者、目标版本、结论、理由和时间。后台只授权现有管理员身份,不让普通作者调用审核动作。
- 更新送审时旧 `activeVersionId` 继续服务目录、详情与游玩。审核通过并完成对象可读验证后,一次事务切换当前公开版本和公开资料;新版本上传、校验、审核或对象安装失败均不改变旧版本。
- AGC 发布面板在无绑定时显示“首次发布”,存在绑定时显示“更新游戏”,回填当前版本号、状态和建议目标版本号。首版不做完整版本历史/回滚管理,只提供目标版本号选择、当前状态和新版本发布。
- 版本状态为 `awaiting_upload → uploaded → validating → pending_review → published`。上传确定失败进入 `upload_failed`,验证失败进入 `validation_failed`,人工拒绝进入 `rejected`;尚未公开提交可以撤回为 `cancelled`,已公开实例可撤销为 `revoked`。同一用户版本标签的新内容必须创建新提交实例。
- 首版建议人工审核。审核员检查游戏资料、真实桌面运行、声明移动适配、内容与外部请求被阻断的行为;自动包校验通过只进入 `pending_review`,不自动公开。审核记录保存审核者、目标 `versionId`、结论、理由和时间。后台只授权现有管理员身份,不让普通作者调用审核动作。
- 更新送审时旧 `activeVersionId` 继续服务目录、详情与游玩。审核通过并完成对象可读验证后,一次事务切换当前公开版本和公开资料;新提交上传、校验、审核或对象安装失败均不改变旧版本。
- AGC 发布面板在无绑定时显示“首次发布”,存在绑定时显示“更新游戏”,回填当前 `projectVersion`、线上版本状态和建议值。首版不做完整版本历史/回滚管理,但允许用户修改项目版本标签、重复提交同版本和回退到旧版本标签。
### 幂等、并发与恢复