收口 M3 复核遗留:文档如实口径、fork-source 状态说明、forkAuthorization 机器守卫、e2e 引用去行号
- 技术方案 §3.4:删掉「GET /games/{gameId} 追加 forkSourceAvailable」——实现里不存在该字段;改为如实口径:改造入口显隐只依据 forkAuthorization,真实可复刻形态由 /fork-source 的 source 回答,若 M2b 要区分「可源码级改造 / 只能参考」届时再加
- 实施计划(M1)§5:同步去掉 forkSourceAvailable 并注明「未实现、也不需要」,保留其余字段清单不动
- 技术方案 §2.6 时序图:说明字句从「GET …/fork-source 是待实现接口」改为「M2a 已实现(形状见 §3.4 登录用户表)」,并在图内加一行 Note 标注「图中字段名是 M2b 目标形状」;图属目标形态的免责声明保留
- parity 脚本:game_payload 增加 mustEmit ['forkAuthorization']——该字段 TS 侧可选(旧响应可省),但公开与作者响应必须发出,否则详情页授权徽章与改造入口会静默退化成「禁止共创」;public_game_payload 以 game_payload 为 base,因此一并受保护
- e2e 脚本头部:把全部行号引用(含已过期 2–4 行的那些)改为「文件 + 符号」引用(router()/lineage_read_or_not_found()/GameDistributionLineageNode/lineage.rs 常量与函数等),并删除「消费链路在未提交的 M2a WIP 里」这类会过期的措辞,改为「已在 M2a 落地」;只改注释,断言逻辑未动
This commit is contained in:
@@ -105,6 +105,11 @@ const RESPONSE_BUILDERS = [
|
||||
{
|
||||
fn: 'game_payload',
|
||||
ts: 'GameDistributionGame',
|
||||
// `forkAuthorization` 在 TS 里是可选的(旧响应可省略),但**公开与作者响应都必须发出**它:
|
||||
// 详情页的授权徽章与「改造这个作品」入口都读它,缺了会静默退化成「禁止共创」。
|
||||
// mustEmit 是唯一能表达「可选字段在这条路径上必出」的机制,所以钉在这里;
|
||||
// public_game_payload / owner_game_entry_payload 都以它为 base,因此一并受保护。
|
||||
mustEmit: ['forkAuthorization'],
|
||||
nested: [
|
||||
{ key: 'author', ts: 'GameDistributionAuthor' },
|
||||
{ key: 'deviceSupport', ts: 'GameDistributionDeviceSupport' },
|
||||
|
||||
@@ -10,30 +10,37 @@
|
||||
// E2E_CHROMIUM_EXECUTABLE 指定 Chromium 可执行文件(默认用 Playwright 自带浏览器)
|
||||
// E2E_LINEAGE_LABEL_* 覆盖前端文案(默认对齐实现里的字符串)
|
||||
//
|
||||
// 参考的仓库既有实现与脚本(本脚本按同一风格写成,契约形状全部来自代码而不是猜测):
|
||||
// [1] 路由挂载(公开、匿名、no-store):server-rs/crates/api-server/src/modules/game_distribution.rs:419-426(public_games)
|
||||
// [2] 「不可读即 404」映射:api-server/src/modules/game_distribution.rs:1090-1092(lineage_read_or_not_found)
|
||||
// [3] 两个 handler:api-server/src/modules/game_distribution.rs:1096(get_game_lineage)/ :1114(get_game_derived_games)
|
||||
// [4] 节点 DTO 的 7 个键:server-rs/crates/shared-contracts/src/game_distribution.rs:262-281
|
||||
// 响应::283-293(LineageResponse)/ :295-301(DerivedResponse)
|
||||
// [5] 上限 200 / 锚点可读性 / 稳定排序:server-rs/crates/module-game-distribution/src/lineage.rs:22 / :28-30 / :135-143
|
||||
// [6] 作者软删除:api-server/src/modules/game_distribution.rs:1518-1550;事务语义(撤销当前公开版本 + deleted_at)
|
||||
// server-rs/crates/spacetime-module/src/game_distribution.rs:3599-3660
|
||||
// [7] 改编声明 DTO:shared-contracts/src/game_distribution.rs:241-245 + :367-368;
|
||||
// 消费点 api-server/...:1611-1615;事务校验 spacetime-module/...:2155-2160 + :2250-2254
|
||||
// [8] 发布链路(建版本 → 传包 → 送审 → 管理员通过)照抄 scripts/check-game-distribution-media-e2e.mjs:391-400,431-450,455-470,479-495,523-527,561-573
|
||||
// [9] 封面直传 + 确认:scripts/check-game-distribution-owner-isolation.mjs:97-150
|
||||
// [10] 从 .app/dev-stack.json 读地址:scripts/check-game-distribution-ratings-e2e.mjs:15-27
|
||||
// [11] Playwright 装载 / 启动 / 网页登录:scripts/check-game-distribution-web-publish-e2e.mjs:51-57,74-90,148-159
|
||||
// [12] 前端契约:详情页入口 GameDetailPage.tsx:409「查看创作族谱」;族谱页 GameLineagePage.tsx:65-70(节点卡片类名)、
|
||||
// :93「原作品已不可用」、:163-164 标题;路由 /games/lineage:src/routing/activeAppPageRoutes.ts:18
|
||||
// [13] 节点作者名读时联账号表:spacetime-module/src/game_distribution.rs:4294-4308(所以脚本会先给作者改名,让「删除后不外发作者名」这条断言有意义)
|
||||
// 参考的仓库既有实现(按**符号**引用,不写行号,避免随改动腐化):
|
||||
// [1] 路由挂载(公开、匿名、no-store):server-rs/crates/api-server/src/modules/game_distribution.rs 的
|
||||
// `router()` 里 `public_games` 子路由
|
||||
// [2] 「不可读即 404」映射:api-server/src/modules/game_distribution.rs 的 `lineage_read_or_not_found()`
|
||||
// [3] 两个 handler:api-server/src/modules/game_distribution.rs 的 `get_game_lineage()` / `get_game_derived_games()`
|
||||
// [4] 节点 DTO 的 7 个键:server-rs/crates/shared-contracts/src/game_distribution.rs 的 `GameDistributionLineageNode`;
|
||||
// 两个响应:同文件的 `GameDistributionLineageResponse` / `GameDistributionDerivedResponse`
|
||||
// [5] 上限 200 / 锚点可读性 / 稳定排序:server-rs/crates/module-game-distribution/src/lineage.rs 的
|
||||
// `GAME_DISTRIBUTION_LINEAGE_NODE_LIMIT` / `lineage_anchor_readable()` / `stable_node_order()`
|
||||
// [6] 作者软删除:api-server/src/modules/game_distribution.rs 的 `delete_owner_game()`;
|
||||
// 事务语义(撤销当前公开版本 + 写 deleted_at):
|
||||
// server-rs/crates/spacetime-module/src/game_distribution.rs 的 `delete_game_distribution_game_tx()`
|
||||
// [7] 改编声明 DTO:shared-contracts/src/game_distribution.rs 的 `GameDistributionForkDeclaration`;
|
||||
// 消费点 api-server/src/modules/game_distribution.rs 的 `create_game()`;
|
||||
// 事务校验 spacetime-module/src/game_distribution.rs 的 `resolve_game_distribution_fork_declaration_tx()`
|
||||
// [8] 发布链路(建版本 → 传包 → 送审 → 管理员通过)照抄 scripts/check-game-distribution-media-e2e.mjs 的 `main()`
|
||||
// [9] 封面直传 + 确认:scripts/check-game-distribution-owner-isolation.mjs 的 `uploadCover()` / `main()`
|
||||
// [10] 从 .app/dev-stack.json 读地址:scripts/check-game-distribution-ratings-e2e.mjs 模块顶部的 dev-stack 读取
|
||||
// [11] Playwright 装载 / 启动 / 网页登录:scripts/check-game-distribution-web-publish-e2e.mjs 的
|
||||
// `loadPlaywright()` / `loginThroughWebUi()`
|
||||
// [12] 前端契约:详情页入口 src/components/game-distribution/GameDetailPage.tsx 的 `GameDetailContent`
|
||||
// (共创信息卡里的「查看创作族谱」按钮);族谱页 src/components/game-distribution/GameLineagePage.tsx 的
|
||||
// `LineageNodeCard`(节点卡片类名、「原作品已不可用」、标题按钮);路由 /games/lineage:
|
||||
// src/routing/activeAppPageRoutes.ts 的 `STAGE_ROUTE_ENTRIES`
|
||||
// [13] 节点作者名读时联账号表:spacetime-module/src/game_distribution.rs 的 `game_distribution_lineage_author_name()`
|
||||
// (所以脚本会先给作者改名,让「删除后不外发作者名」这条断言有意义)
|
||||
//
|
||||
// 依赖提示(重要):
|
||||
// 改编声明 `fork: { parentGameId, parentVersionId }` 的消费链路当前在**未提交的 M2a WIP** 里
|
||||
// (工作树 api-server/...:1611-1615 已接,但提交基线 4207d24f0 尚未包含)。在 M2a 落地前:
|
||||
// - A 段(404 规则)与 E 段的「未公开锚点 404」可以照跑;
|
||||
// - B/C 段(真实树、软删除降级)会因为创建 B 时 fork 声明不生效而失败 —— 那是依赖未就绪,不是脚本问题。
|
||||
// 依赖提示:改编声明 `fork: { parentGameId, parentVersionId }` 的消费链路**已在 M2a 落地**
|
||||
// (shared-contracts 的 DTO → api-server `create_game()` → spacetime-module
|
||||
// `resolve_game_distribution_fork_declaration_tx()`),本脚本按已落地的形状断言;如果 B/C 段
|
||||
// 因创建 B 时声明不生效而失败,那说明对应实现被回退了,不是脚本问题。
|
||||
//
|
||||
// 契约假设(读代码确认,不猜):
|
||||
// - anchor 必须公开可读,否则 /lineage 与 /derived 都返回 **404**(不是 200 空树、也不是 409)。
|
||||
|
||||
Reference in New Issue
Block a user