修复买断制付费评审问题:后台消耗统计、定价上限校验、付费入口自动化断言
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m17s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m20s
Project CI / Frontend tests (pull_request) Successful in 3m29s
Project CI / Backend tests (pull_request) Successful in 7m53s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m23s
Project CI / Native shell tests (pull_request) Successful in 7m48s
Project CI / Repository checks (pull_request) Successful in 5m36s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m17s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m20s
Project CI / Frontend tests (pull_request) Successful in 3m29s
Project CI / Backend tests (pull_request) Successful in 7m53s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m23s
Project CI / Native shell tests (pull_request) Successful in 7m48s
Project CI / Repository checks (pull_request) Successful in 5m36s
- admin.rs:钱包流水来源映射补齐第 17 个变体(索引 16 → game_purchase),后台「消耗泥点」白名单新增 game_purchase,并抽出效果分类与单行累加函数
- profile.rs:消耗口径抽出 profile_wallet_ledger_source_counts_as_consumption,消费投影增量、历史花费重建、投影初始化三处一并纳入 GamePurchase
- module-game-distribution/errors.rs:价格上限文案改为插值 MAX_GAME_PRICE_MUD_POINTS,并新增文案断言
- 新增 scripts/check-game-distribution-price-limit-parity.mjs 并挂进 npm run lint(随 Repository checks 在 CI 生效):断言 TS / 服务端 Rust / AGC Rust 常量与网页侧别名四处同源
- api-server 发行网关抽出可注入 loader 的 serve_public_release_asset,付费 404 严格发生在读取包字节之前;播放会话准入抽出 resolve_paid_play_session_entitlement
- 新增 api-server 单测:付费发行路径 404 且零次读包字节、免费放行且读到包字节、未购买 403 与作者 / 已购买 / 管理员放行
- spacetime-module:把「先判定后扣费」从源码扫描改为 resolve_game_purchase_pre_charge_plan 纯函数断言,删除 include_str 源码切片用例
- E2E 脚本:平台同源断言缺配置时记 SKIP 并在报告末尾汇总 SKIP 清单,E2E_REQUIRE_PLATFORM_ORIGIN=1 时缺配置直接 FAIL,汇总行改为输出 PASS/FAIL/WARN/SKIP 计数
- 修正注释里不存在的路由 POST /api/game-distribution/play-sessions(真实为 POST /api/game-distribution/games/{gameId}/play-session)与「管理员令牌 403」口径(403 需带 admin 角色的用户令牌)
This commit is contained in:
@@ -115,6 +115,6 @@ curl -sSI -H 'Accept-Encoding: br' \
|
||||
|
||||
- 付费游戏的可玩入口是 `POST /api/game-distribution/games/<gameId>/play-session` 换到的 `/api/game-distribution/play-sessions/<token>/`,直接作为 sandbox iframe 的 `src`;包内相对资源沿同一前缀解析。该前缀落在 `/api/*` 上,而通用 `/api` location 必须转发 Cookie(`/api/auth/*` 依赖 refresh cookie),Cookie 一旦被转发到 `api-server` 播放网关就会命中它的 403 纵深防御,iframe 与包内每个资源都不可用。
|
||||
- 因此三份常驻模板(`genarrative.conf`、`genarrative-dev-http.conf`、容器 `deploy/container/nginx.conf`)都在通用 `/api` location 之前内联 `location ^~ /api/game-distribution/play-sessions/`,代理头、`client_max_body_size 210m`、`limit_conn` / `limit_req`、超时与维护判断都与通用 `/api` location 一致,只多一条 `proxy_set_header Cookie ""`。
|
||||
- `^~` 不能省:不加时 nginx 会先命中正则 location `~ ^/api(?:/|$)`,Cookie 又被转发回去。前缀末尾的斜杠也不能省:创建会话的 `POST /api/game-distribution/play-sessions` 需要账号凭证,必须继续走通用 `/api` 并保留 Cookie。
|
||||
- `^~` 不能省:不加时 nginx 会先命中正则 location `~ ^/api(?:/|$)`,Cookie 又被转发回去。前缀末尾的斜杠只影响裸前缀 `/api/game-distribution/play-sessions`(无 token):该形态继续走通用 `/api`,而 api-server 在这个前缀下只注册了 GET 入口与包内资源,创建会话是 `POST /api/game-distribution/games/<gameId>/play-session`,不在此前缀下,因此不存在「带账号凭证却落在清 Cookie 前缀里」的请求;`/play-sessions/<token>` 与 `/play-sessions/<token>/…` 都落在该前缀内、都会被清 Cookie。
|
||||
- 本地 dev 由 `vite.config.ts` 里排在 `/api/game-distribution` 之前的同名前缀规则做同一件事(`proxyReq.removeHeader('cookie')`);`api-server` 播放网关的 403 纵深防御不放宽,只保证边缘/dev 转发时不带 Cookie。
|
||||
- 门禁:`npm run check:nginx-spa-routes` 对三份模板断言该 `^~` 前缀 location 存在、清空 Cookie、代理头齐全且排在通用 `/api` location 之前;`npm run check:pingora-route-parity` 断言矩阵里的 `play_sessions_gateway` 用例(以及 Pingora 的 `RouteDecision::PlaySessionGateway`)指向独立的清 Cookie 转发,不会被合并回通用 `/api` 规则。
|
||||
|
||||
@@ -121,7 +121,9 @@ server {
|
||||
# 限流、超时、维护判断都保持一致),唯一差别是清空 Cookie:播放会话不读账号凭证,而
|
||||
# api-server 播放网关对带平台 refresh Cookie 的请求返回 403(纵深防御保留)。
|
||||
# 前缀 location 必须写 `^~`:不加时正则 location `~ ^/api(?:/|$)` 会先命中,Cookie 又会被转发。
|
||||
# 只匹配带尾斜杠的前缀,创建会话的 `POST /api/game-distribution/play-sessions` 仍走通用 `/api`。
|
||||
# 只匹配带尾斜杠的前缀:`/play-sessions/<token>` 与 `/play-sessions/<token>/…` 都落在该前缀内,
|
||||
# 裸 `/api/game-distribution/play-sessions` 仍走通用 `/api`。该前缀下 api-server 只注册 GET
|
||||
# 入口与包内资源;创建会话是 `POST /api/game-distribution/games/<gameId>/play-session`,不在此前缀下。
|
||||
location ^~ /api/game-distribution/play-sessions/ {
|
||||
default_type application/json;
|
||||
client_max_body_size 210m;
|
||||
|
||||
@@ -149,7 +149,9 @@ server {
|
||||
# 限流、超时、维护判断都保持一致),唯一差别是清空 Cookie:播放会话不读账号凭证,而
|
||||
# api-server 播放网关对带平台 refresh Cookie 的请求返回 403(纵深防御保留)。
|
||||
# 前缀 location 必须写 `^~`:不加时正则 location `~ ^/api(?:/|$)` 会先命中,Cookie 又会被转发。
|
||||
# 只匹配带尾斜杠的前缀,创建会话的 `POST /api/game-distribution/play-sessions` 仍走通用 `/api`。
|
||||
# 只匹配带尾斜杠的前缀:`/play-sessions/<token>` 与 `/play-sessions/<token>/…` 都落在该前缀内,
|
||||
# 裸 `/api/game-distribution/play-sessions` 仍走通用 `/api`。该前缀下 api-server 只注册 GET
|
||||
# 入口与包内资源;创建会话是 `POST /api/game-distribution/games/<gameId>/play-session`,不在此前缀下。
|
||||
location ^~ /api/game-distribution/play-sessions/ {
|
||||
default_type application/json;
|
||||
client_max_body_size 210m;
|
||||
|
||||
Reference in New Issue
Block a user