回写游戏买断制泥点付费真实栈验收证据并删除实施计划
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
主规范合同章「验收标准与证据」表逐行回写真实本地栈 E2E 与单元/组件门禁结果,缺证据的覆盖边界如实标注未覆盖 主规范合同章补充说明运行时证据来自人工验收脚本 check:game-distribution-purchase-e2e(76 PASS / 0 FAIL / 1 WARN),不在 CI 自动门禁内 主规范合同章「实现约束与已知风险」新增 E2E 人工脚本不在 CI 覆盖、上线前私有桶 E2E_REQUIRE_PRIVATE_BUCKET 复核两条 主规范合同章表头删除已废弃的实施计划链接 里程碑验收复选框勾选已满足项并补证据说明,新增「未覆盖边界」保持未勾选(管理员安全下架会话失效、多账号/多游戏混合并发)并注明原因 里程碑「证据要求」补充已执行的人工验收结果与唯一 WARN 说明,Status 保持 implemented-awaiting-runtime-acceptance 删除 docs/project-memory/plans/【实施计划】游戏买断制泥点付费与播放鉴权-2026-10-05.md 并同步 docs/README.md 条目为已实现、E2E 76 PASS、待用户验收、未部署
This commit is contained in:
+1
-1
@@ -24,7 +24,7 @@
|
||||
- [后台游戏评价管理合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#后台游戏评价管理合同):查找、分页、隐藏/恢复/删除、必填原因、统计与个人状态联动;已实现并通过本地验证,待用户验收,未部署。
|
||||
- [后台游戏评价管理里程碑](./project-memory/plans/【里程碑】后台游戏评价管理-2026-10-01.md)与[实施计划](./project-memory/plans/【实施计划】后台游戏评价管理-2026-10-01.md):单里程碑范围、接口/schema 边界及验收要求;本地证据已回写主规范。
|
||||
- [游戏广场评分展示合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏广场评分展示合同)、[里程碑](./project-memory/plans/【里程碑】游戏广场评分展示-2026-10-01.md)与[实施计划](./project-memory/plans/【实施计划】游戏广场评分展示-2026-10-01.md):已实现并通过本地定向验证,待用户验收,未部署;公开列表/详情携带真实摘要,卡片显示一位小数均分与人数,复用有效评价统计。
|
||||
- [游戏买断制泥点付费与播放鉴权合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏买断制泥点付费与播放鉴权合同)、[里程碑](./project-memory/plans/【里程碑】游戏买断制泥点付费与播放鉴权-2026-10-05.md)与[实施计划](./project-memory/plans/【实施计划】游戏买断制泥点付费与播放鉴权-2026-10-05.md):已实现,本机真实栈 E2E 通过,待用户验收;未部署;作者可选买断制泥点付费,购买后永久可玩,后台审核可见价格且审核员不限次试用。
|
||||
- [游戏买断制泥点付费与播放鉴权合同](./【玩法创作】平台入口与玩法链路-2026-05-15.md#游戏买断制泥点付费与播放鉴权合同)与[里程碑](./project-memory/plans/【里程碑】游戏买断制泥点付费与播放鉴权-2026-10-05.md):已实现,本机真实栈 E2E 76 PASS,待用户验收;未部署;人工验收脚本 `check:game-distribution-purchase-e2e` 不在 CI 自动门禁内;作者可选买断制泥点付费,购买后永久可玩,后台审核可见价格且审核员不限次试用。
|
||||
- [游戏游玩次数计数](./adr/【ADR】游戏游玩次数计数-2026-10-03.md):点「开始游戏」前端上报一次游玩,api-server 纯内存聚合(5s flush、30min 去重、`IP+game` 限流、关停不强制 flush),批量 procedure 自增现有 `game_distribution_game.play_count`,不 bump `updated_at`。
|
||||
- [外部 OpenAPI 与 API Key 接入方案](./【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md)
|
||||
- [外部 MCP 语义工具说明与参数设计](./technical/【技术方案】外部MCP语义工具说明与参数设计-2026-09-23.md):15 个新增语义工具与全部原工具并存,复用现有 External API;包含工具说明、action、参数、幂等和兼容合同。
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# 【实施计划】游戏买断制泥点付费与播放鉴权
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Milestone | `docs/project-memory/plans/【里程碑】游戏买断制泥点付费与播放鉴权-2026-10-05.md` |
|
||||
| Status | ready |
|
||||
| Owner | Genarrative Agent |
|
||||
|
||||
## 修改边界
|
||||
|
||||
- 允许修改:
|
||||
- `server-rs/crates/module-game-distribution`:定价、购买与播放授权的领域规则与纯内存测试。
|
||||
- `server-rs/crates/module-runtime`:新增 `game_purchase` 流水来源类型。
|
||||
- `server-rs/crates/spacetime-module`:游戏表价格字段、购买表、相关 procedure、`migration.rs`。
|
||||
- `server-rs/crates/spacetime-client`:facade 与 row mapper。
|
||||
- `server-rs/crates/api-server`:创建/更新版本接受价格、购买接口、播放会话接口、公开详情与发行网关鉴权、admin 展示。
|
||||
- `server-rs/crates/shared-contracts`、`packages/shared`:价格、购买态、购买与播放会话 DTO 及钱包文案。
|
||||
- 主站 `src/components/game-distribution`、`src/services/gameDistributionClient.ts` 与发布/详情/游玩/广场相关组件。
|
||||
- `apps/admin-web`:审核详情与待审列表价格展示。
|
||||
- 文档、后端表目录、生成绑定与定向测试。
|
||||
- 明确不修改:`/api/external/v1` 及其 OpenAPI;AGC 发布面板;评分/评价;免费游戏公开链路行为。
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. 主规范与里程碑评审确认;主规范已解除“不做交易”排除并新增合同章。
|
||||
2. 领域与 schema:游戏表末尾追加 `price_mud_points`;新增 `game_distribution_purchase`;`module-game-distribution` 定价/购买/授权规则与纯内存测试;同步 `migration.rs`、表目录、生成绑定并运行 schema 检查。
|
||||
3. 钱包:`RuntimeProfileWalletLedgerSourceType` 追加 `game_purchase`;购买时原子扣费并写流水;同步 Rust/TS 契约与前端/后台文案。
|
||||
4. API 与鉴权:创建/更新版本接受并校验价格;购买接口(`Idempotency-Key` + `(user_id, game_id)` 唯一);播放会话接口;公开详情返回价格与购买态并按需隐藏入口;发行网关对付费游戏拒绝公开路径;admin 详情与列表展示价格。
|
||||
5. 前端:发布页定价字段与校验;详情页价格与购买(复用泥点确认弹窗与钱包 store);游玩页经播放会话挂载 iframe;广场角标(可选)。
|
||||
6. 后台:审核详情与待审列表价格展示。
|
||||
7. 回写主规范、产出真实栈 smoke 与验收证据矩阵,删除本实施计划。
|
||||
|
||||
## 验证命令
|
||||
|
||||
1. `cargo test -p module-game-distribution`
|
||||
2. `cargo test -p api-server game_distribution`
|
||||
3. `npm run spacetime:generate && npm run check:spacetime-schema`
|
||||
4. `npm run typecheck`
|
||||
5. 定向 `npx vitest run src/components/game-distribution` 与 `apps/admin-web` 相关用例
|
||||
6. `npm run check:encoding`、`git diff --check`
|
||||
7. 真实本地栈 smoke(见里程碑“证据要求”)
|
||||
|
||||
## 风险与回滚点
|
||||
|
||||
- schema:游戏表只末尾追加带默认值字段,购买为新独立表;如迁移不可用,回滚点是不开放定价选项,保留领域与接口的非持久化部分。
|
||||
- 付费鉴权:播放会话未就绪时,回滚点是付费游戏只做“购买态 + 平台页隐藏入口”,但不得对外宣称已具备防绕过能力。
|
||||
- 钱包:扣费与购买记录必须同事务;无法原子时回滚到不开放购买,只保留价格展示。
|
||||
- 免费链路:若改动影响免费游戏,优先回滚该分支,保证免费回归为绿。
|
||||
@@ -35,18 +35,25 @@
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 作者网页发布可选「免费」或「买断制 N 泥点」;负数/超上限/非整数被前后端同时拦截。
|
||||
- [ ] 后台审核详情展示该版本价格;无价格的历史版本按免费展示。
|
||||
- [ ] 审核员不限次数试玩待审付费版本,不校验购买、不扣泥点。
|
||||
- [ ] 未购买用户详情可见资料但无可播放入口;直连 `/games/<gameId>/` 返回 404。
|
||||
- [ ] 余额不足购买失败,余额、账单与购买记录都不变。
|
||||
- [ ] 购买成功:余额减少 N、账单出现 `game_purchase` 流水、购买记录唯一、可反复游玩不再扣费。
|
||||
- [ ] 双击、并发与响应丢失重试只扣一次。
|
||||
- [ ] 作者本人与管理员免购买即可游玩付费作品且不扣费。
|
||||
- [ ] 免费游戏的发布、详情、游玩与计数链路无行为变化。
|
||||
- [x] 作者网页发布可选「免费」或「买断制 N 泥点」;负数/超上限/非整数被前后端同时拦截。证据:真实本地栈 E2E 价格 `1000001` → 400 且不落版本,`0` / `1000000` → 200;`cargo test -p module-game-distribution` 29 passed、`cargo test -p api-server game_distribution` 53 passed 覆盖定价校验,网页发布表单定价定向 Vitest 覆盖前端拦截。
|
||||
- [x] 后台审核详情展示该版本价格;无价格的历史版本按免费展示。证据:`cargo test -p api-server game_distribution` 53 passed(`private_version_payload` / `version_detail_payload` 输出 `priceMudPoints`,历史无价格版本按 0);admin-web 审核价格展示定向 Vitest。
|
||||
- [x] 审核员不限次数试玩待审付费版本,不校验购买、不扣泥点。证据:真实本地栈 E2E 审核员两次试玩待审付费版本均 200、两次包内字节一致,作者与审核员余额/流水均不变。
|
||||
- [x] 未购买用户详情可见资料但无可播放入口;直连 `/games/<gameId>/` 返回 404。证据:真实本地栈 E2E 详情 `priceMudPoints=30` / `purchased=false` / `entryUrl=null`,发行网关与平台同源均 404,创建会话 403,未登录 401。
|
||||
- [x] 余额不足购买失败,余额、账单与购买记录都不变。证据:真实本地栈 E2E 返回 400 `INSUFFICIENT_MUD_POINTS`,余额与流水不变。
|
||||
- [x] 购买成功:余额减少 N、账单出现 `game_purchase` 流水、购买记录唯一、可反复游玩不再扣费。证据:真实本地栈 E2E 扣 30(120→90),`game_purchase` 流水与购买行各 1 条,重复进入不再扣费。
|
||||
- [x] 双击、并发与响应丢失重试只扣一次。证据:真实本地栈 E2E 同 key 重放、换 key 重复购买均不再扣费;两路不同 key 真并发返回 200/200、只有一个 `replayed=false`、余额只扣一次、购买记录 1 条。
|
||||
- [x] 作者本人与管理员免购买即可游玩付费作品且不扣费。证据:真实本地栈 E2E 作者(自购 400 `GAME_PURCHASE_OWNER_EXEMPT`、余额/流水不变、播放会话 200)与管理员(管理员令牌创建播放会话 200、入口 200);管理员免购买经 play-session 管理员分支实现。
|
||||
- [x] 免费游戏的发布、详情、游玩与计数链路无行为变化。证据:真实本地栈 E2E 免费游戏详情保留入口、发行网关 200、匿名创建会话 200 且不签发令牌。
|
||||
|
||||
## 未覆盖边界(保持未勾选)
|
||||
|
||||
- [ ] 管理员安全下架后的播放会话失效:本轮未单独运行,与作者下架共用同一 404 关闭路径。
|
||||
- [ ] 多账号 / 多游戏混合并发购买:本轮只覆盖单游戏、单账号的两路真并发。
|
||||
|
||||
## 证据要求
|
||||
|
||||
- 自动化:Rust 定向测试(定价校验、购买幂等与并发、授权判定、状态机)、Vitest(发布表单定价、详情购买态、游玩页会话挂载、审核价格展示)、schema/绑定与编码门禁。
|
||||
- 运行时:真实本地栈跑通「发布付费游戏 → 后台审核可见价格并试玩 → 通过 → 未购买访问失败 → 购买 → 游玩 → 重复游玩不扣费」。
|
||||
- 边界:并发购买、余额不足、下架/封禁后播放会话失效、猜测 URL 直连、免费游戏回归。
|
||||
|
||||
已执行(2026-10-05,人工验收):`npm run check:game-distribution-purchase-e2e` 在本机真实 SpacetimeDB / api-server / OSS 一次跑通 76 PASS / 0 FAIL / 1 WARN,exit 0,24.1s,teardown 无残留。唯一 WARN 为「管理员令牌购买」在当前产品形态不可达(管理员免购买经 play-session 管理员分支实现,购买路由的 403 `GAME_PURCHASE_ADMIN_NOT_ALLOWED` 分支作为纵深防御保留)。该脚本不在 CI 自动门禁内,CI 绿不代表该链路已验证;本里程碑结论最高到“本机真实栈验证通过,待用户验收,未部署”。
|
||||
|
||||
@@ -563,7 +563,6 @@
|
||||
| Date | 2026-10-05 |
|
||||
| 适用边界 | 主站游戏分发(`/games`)的作者买断制定价、泥点购买、付费游玩鉴权与后台审核价格展示;不含创作者结算 |
|
||||
| 里程碑 | [游戏买断制泥点付费与播放鉴权](./project-memory/plans/【里程碑】游戏买断制泥点付费与播放鉴权-2026-10-05.md) |
|
||||
| 实施计划 | [实施计划](./project-memory/plans/【实施计划】游戏买断制泥点付费与播放鉴权-2026-10-05.md) |
|
||||
|
||||
### 目标
|
||||
|
||||
@@ -626,6 +625,8 @@
|
||||
- 播放会话是 `api-server` 进程内短期会话,不持久化到 SpacetimeDB:多副本部署需要粘性路由,进程重启即全部失效,与既有后台待审预览会话同构。
|
||||
- 播放始终解析“当前公开版本”:作者发布并审核通过新版本后,旧会话继续玩到的是新版本包,与买断制永久所有权随 `gameId` 而非版本的口径一致。
|
||||
- 已知同类风险(本次只记录、不修):后台待审预览入口 `/api/game-distribution/admin-previews/{token}/` 与播放会话同属 `/api` 前缀,`api-server` 预览网关同样对带可解析平台 refresh Cookie 的请求返回 403;本次只对播放会话前缀做了边缘/dev 清 Cookie 加固,预览前缀未加固。
|
||||
- `scripts/check-game-distribution-purchase-e2e.mjs`(`npm run check:game-distribution-purchase-e2e`)是人工验收脚本,需要 `E2E_ADMIN_USER` / `E2E_ADMIN_PASSWORD` 与真实 SpacetimeDB / api-server / OSS,不在 CI 自动门禁内;CI 绿不代表付费链路的运行时行为已验证,发布前必须人工运行并保留结果。
|
||||
- 上线前需用 `E2E_REQUIRE_PRIVATE_BUCKET=1` 复核生产桶不允许匿名直取发行包(既有要求,非本轮新增)。
|
||||
|
||||
### 契约与迁移
|
||||
|
||||
@@ -638,15 +639,17 @@
|
||||
|
||||
| 条款 | 验收方式 | 证据 |
|
||||
| --- | --- | --- |
|
||||
| 定价 | 网页发布可选「免费/买断制」并拦截非法值,前后端口径一致 | 待补 |
|
||||
| 后台可见 | 审核详情与待审列表显示该版本价格 | 待补 |
|
||||
| 审核试玩 | 审核员不限次试玩待审付费版本,不校验购买、不扣泥点 | 待补 |
|
||||
| 购买 | 余额不足失败且不变更;成功扣 N、账单出现 `game_purchase` 流水、购买记录唯一 | 待补 |
|
||||
| 幂等 | 双击、并发、响应丢失重试只扣一次 | 待补 |
|
||||
| 播放鉴权 | 未购买直连公开入口 404;购买后可反复游玩且不再扣费 | 待补 |
|
||||
| 免购买游玩 | 作者与管理员可游玩付费作品且不扣费 | 待补 |
|
||||
| 免费回归 | 免费游戏发布/详情/游玩/计数无行为变化 | 待补 |
|
||||
| 工程门禁 | schema/绑定、两端类型、定向测试、编码与 diff 检查通过 | 待补 |
|
||||
| 定价 | 网页发布可选「免费/买断制」并拦截非法值,前后端口径一致 | 真实本地栈 E2E:价格 `1000001` → 400 且不落版本,`0` 与 `1000000` → 200;`cargo test -p module-game-distribution` 29 passed(`normalize_game_price_mud_points` 上限)、`cargo test -p api-server game_distribution` 53 passed(`validate_version_declaration` 定价校验);网页发布表单定价定向 Vitest |
|
||||
| 后台可见 | 审核详情与待审列表显示该版本价格 | `cargo test -p api-server game_distribution` 53 passed(`private_version_payload` / `version_detail_payload` 输出 `priceMudPoints`,历史无价格版本按 0,不回退游戏行当前价);admin-web 审核价格展示定向 Vitest |
|
||||
| 审核试玩 | 审核员不限次试玩待审付费版本,不校验购买、不扣泥点 | 真实本地栈 E2E:审核员两次试玩待审付费版本均 200、两次包内字节一致,作者与审核员余额/流水均不变 |
|
||||
| 购买 | 余额不足失败且不变更;成功扣 N、账单出现 `game_purchase` 流水、购买记录唯一 | 真实本地栈 E2E:余额不足 400 `INSUFFICIENT_MUD_POINTS` 且余额与流水不变;成功购买扣 30(120→90),`game_purchase` 流水与购买行各 1 条;同 key 重放与换 key 重复购买都不再扣费 |
|
||||
| 幂等 | 双击、并发、响应丢失重试只扣一次 | 真实本地栈 E2E:同 key 重放、换 key 重复购买均不再扣费;两路不同 key 真并发返回 200/200,只有一个 `replayed=false`,余额只扣一次、购买记录 1 条。多账号/多游戏混合并发未覆盖 |
|
||||
| 播放鉴权 | 未购买直连公开入口 404;购买后可反复游玩且不再扣费 | 真实本地栈 E2E:未购买时详情 `priceMudPoints=30` / `purchased=false` / `entryUrl=null`,直连发行网关与平台同源均 404,创建会话 403,未登录 401;购买后可玩且重复进入不再扣费;伪造令牌 404;直连带平台 Cookie 403、经 dev 代理(该前缀清 Cookie)200;作者下架后旧会话入口与资源均 404。管理员安全下架后的会话失效未单独跑(与作者下架共用同一 404 关闭路径) |
|
||||
| 免购买游玩 | 作者与管理员可游玩付费作品且不扣费 | 真实本地栈 E2E:作者免购买(详情 `purchased=false` 但有 `entryUrl`,自购 400 `GAME_PURCHASE_OWNER_EXEMPT` 且余额/流水不变,播放会话 200);管理员免购买(管理员令牌创建播放会话 200、入口 200)。管理员免购买经 play-session 管理员分支实现;购买路由的 403 `GAME_PURCHASE_ADMIN_NOT_ALLOWED` 分支在当前产品形态不可达(管理员令牌在用户路由先被 `require_bearer_auth` 判 401),作为纵深防御保留并有单元测试 |
|
||||
| 免费回归 | 免费游戏发布/详情/游玩/计数无行为变化 | 真实本地栈 E2E:免费游戏详情保留入口、发行网关 200、匿名创建会话 200 且不签发令牌;`cargo test -p api-server game_distribution` 免费详情 `priceMudPoints=0` / `purchased=false` / 入口保持 |
|
||||
| 工程门禁 | schema/绑定、两端类型、定向测试、编码与 diff 检查通过 | `cargo test -p api-server game_distribution` 53 passed、`cargo test -p module-game-distribution` 29 passed、`cargo test -p spacetime-module game_distribution` 7 passed、`cargo test -p pingora-gateway` 42 passed;`check:game-distribution-dto-parity`、`check:pingora-route-parity`、`check:nginx-spa-routes`、`check:pingora-gateway-smoke`、`check:spacetime-schema`、`check:server-rs-ddd`、两端 typecheck 与定向 Vitest、`check:encoding`、`git diff --check` 全绿 |
|
||||
|
||||
上表运行时证据来自人工验收脚本 `scripts/check-game-distribution-purchase-e2e.mjs`(`npm run check:game-distribution-purchase-e2e`):本机真实 SpacetimeDB / api-server / OSS 一次跑通 76 PASS / 0 FAIL / 1 WARN,exit 0,24.1s,teardown 无残留。该脚本不在 CI 自动门禁内,CI 绿不代表该链路已验证;本表结论最高到“本机真实栈验证通过,待用户验收,未部署”。
|
||||
|
||||
### 已收口决策(2026-10-05)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user