6aa2f97410
Project CI / AI game creator shell Rust lane 1/2 (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 Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (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 2/2 (pull_request) Has been cancelled
产品口径:「子代所有的都算父代的」,并要能溯源「多少是子代给的、多少是自己的」。本期**只做计算**,
不含资金/分成结算。
- 递归定义:`inherited(W) = Σ_{c∈直接子代} total(c)`,`total(W) = own(W) + inherited(W)`;每个后代在它的每个
祖先里只计一次。
- 接口:`GET /api/game-distribution/games/{game_id}/contribution`(Bearer + `no-store`)——**仅该作品作者**:
未登录/失效 401(中间件)、非作者 403(复用既有 owner-mismatch → FORBIDDEN,不新增第二套鉴权)、
作品不存在或根自身已软删 404。响应:`{ gameId, own, inherited, total, byGeneration[], directChildren[],
nodeCount, truncated, truncatedReason }`;指标结构 `ContributionTotals{playCount}` 可扩展(将来加点赞/收藏/收入)。
- 不变量(测试钉住):`inherited == Σ byGeneration.total == Σ directChildren.total`、`total == own + inherited`、
`nodeCount == Σ byGeneration.gameCount`;`byGeneration` 只含后代(绝对代际,升序)。
- 上限与截断:节点 500 / 深度 32;超限如实标 `truncated: true` + `truncatedReason ∈ {node_limit, depth_limit}`,
已计入部分仍自洽(与族谱 `truncated` 同约定,不静默给半个数);遍历只用血缘表既有索引,**不新增表/索引**。
- 契约:shared-contracts 4 个 DTO + TS 镜像 + parity(+4 组 → 66 组);7 个生成绑定(含 procedure)。
- 文档:技术方案新增 `§3.11 贡献归集与权益归因`(定义/归因分解/接口/上限与截断/鉴权口径与理由)+ §3.4 路由行 +
§5.4 实施证据;**任务 B**:反洗稿(相似度校验)从「待拍板」改为「**产品已决定搁置(2026-10-06)**」并从待拍板
清单移除,结算口径统一为「本期只做贡献归集与归因计算」。
- 测试:module-game-distribution **131 passed**(contribution 12 条,含 A→B→C 三层链路不变量);spacetime-module
**304 passed / 1 ignored**(+3 结构断言);spacetime-client 43 passed;api-server game_distribution **107 passed**(+3)。
门禁:wasm build 0;`cargo check --all-targets` 0;`SPACETIME_SCHEMA_BASE_REF=9f4c7d76 npm run check:spacetime-schema`
0(98 表);DTO parity 0(66 组 / 17 构建器 / 15 手拼类型);`check:project-bundle-policy-parity` OK;
`check:encoding` 0(5543 files);`cargo fmt --all --manifest-path server-rs/Cargo.toml -- --check` 0;`git diff --check` 0。
注:本块未提交 `scripts/*.mjs`(`check-game-distribution-lineage-e2e.mjs` / `-theme-e2e.mjs` /
`capture-game-lineage-visual.mjs`)——属其它 owner,工作区保留未提交。
api-server 主工程 crate 占位说明
日期:2026-04-20
1. crate 职责
api-server 是新后端的 Axum 主工程 crate,后续负责:
main.rs启动入口Router装配with_state共享状态注入- 中间件挂载
/healthz、/api/*、SSE 与静态资源兼容层装配- 由
../../scripts/dev.ps1与../../scripts/dev.sh驱动的本地开发启动链路 - 由
../../scripts/test.ps1与../../scripts/test.sh驱动的本地测试链路 - 由
../../scripts/check.ps1与../../scripts/check.sh驱动的本地统一检查链路 - 由
../../scripts/smoke.ps1与../../scripts/smoke.sh驱动的本地启动与协议冒烟链路
2. 当前阶段说明
当前目录已经完成以下基础骨架:
- 目录占位
Cargo.tomlsrc/main.rssrc/app.rssrc/state.rssrc/config.rs- 基础
TraceLayer挂载 - 接入
shared-logging完成tracing subscriber初始化 - 接入
POST /api/auth/entry首版密码登录链路 - 接入
POST /api/auth/password/change登录后修改密码链路 - 接入
POST /api/auth/password/reset手机验证码重置密码链路 - 接入
POST /api/assets/direct-upload-tickets直传票据接口 - 接入
GET /api/auth/me当前用户查询链路 - 接入
POST /api/auth/refreshrefresh token 轮换链路 - 接入
POST /api/auth/logout当前设备退出链路 - 接入
POST /api/assets/objects/confirm上传完成确认链路 - 接入
GET /api/auth/login-options登录方式探测链路 - 接入
POST /api/auth/phone/send-code手机验证码发送链路 - 接入
POST /api/auth/phone/login手机验证码登录链路 - 接入
GET /api/auth/wechat/start微信授权起跳链路 - 接入
GET /api/auth/wechat/callback微信回调换取系统登录态链路 - 接入
POST /api/auth/wechat/bind-phone微信待绑定账号补绑手机号链路 - 接入
POST /api/assets/objects/bind已确认对象绑定业务实体槽位链路 - 接入
POST /api/assets/sts-upload-credentials禁用式 STS 写权限 contract - 接入
POST /api/assets/character-visual/generate - 接入
GET /api/assets/character-visual/jobs/{task_id} - 接入
POST /api/assets/character-visual/publish - 接入
GET /api/assets/character-animation/templates - 接入
POST /api/assets/character-animation/import-video - 接入
GET /api/assets/character-workflow-cache/{character_id} - 接入
POST /api/assets/character-workflow-cache - 接入
POST /api/assets/character-animation/generate - 接入
GET /api/assets/character-animation/jobs/{task_id} - 接入
POST /api/assets/character-animation/publish - 生成资产读取统一走
/api/assets/read-url或 asset object projection
后续与本 crate 直接相关的任务包括:
- 接入统一日志与 tracing
- 接入
request_id - 接入统一错误处理中间件
- 接入 response envelope
- 接入
/healthz - 接入
/api/auth/entry - 接入
/api/assets/direct-upload-tickets - 接入
/api/auth/me - 接入
/api/auth/refresh - 接入
/api/auth/logout - 接入
/api/assets/objects/confirm - 接入
/api/auth/login-options - 接入
/api/auth/phone/send-code - 接入
/api/auth/phone/login - 接入
/api/auth/wechat/start - 接入
/api/auth/wechat/callback - 接入
/api/auth/wechat/bind-phone - 接入
/api/assets/objects/bind - 接入
/api/assets/sts-upload-credentials - 接入
character-visual generate / jobs / publish第一批 OSS 主链 - 接入
character-animation templates / import-video第一批 OSS 草稿链路 - 接入
character-workflow-cache get / save第一批 OSS JSON 草稿链路 - 接入
character-animation generate / jobs / publish第一批 OSS 主链 - 生成资产读取统一走
/api/assets/read-url或 asset object projection
当前 tracing 约定:
- 进程启动时通过
shared-logging统一初始化tracing subscriber。 - 默认日志过滤器来自
GENARRATIVE_API_LOG,未提供时回落到info,tower_http=info。 - HTTP 访问日志统一通过 Axum 路由层的
TraceLayer输出,后续request_id、响应头与错误中间件继续在同一层扩展。 - 本地启动器
npm run dev:api-server和完整联调入口npm run dev会在保留终端实时输出的同时,把同一份cargo/api-server输出持久化到logs/api-server/。如需固定文件或目录,可设置GENARRATIVE_API_SERVER_LOG_FILE或GENARRATIVE_API_SERVER_LOG_DIR。
当前 request context 约定:
- 中间件优先读取来访
x-request-id,未提供时生成新的 UUID。 request_id会统一写入请求extensions与请求头,供 tracing、错误处理中间件和响应头层复用。- 最终响应会回写同一个
x-request-id,保证调用方、日志链路和后续 envelopemeta.requestId可对齐。
当前错误处理中间件约定:
- 对 Axum 默认产生的空
4xx / 5xx响应,统一归一化为 legacy 兼容 JSON 错误体:{ error: { code, message, details? } }。 - 已经带
content-type的业务错误响应不会被覆盖,避免抢走后续 response envelope 的职责。 - 统一错误日志会复用当前请求的
request_id,便于后续和响应头、envelope 元信息串联。
当前 response envelope 约定:
RequestContext已记录request_id、请求开始时间、默认operation与 envelope 协商结果。json_success_body(...)/json_error_body(...)会根据x-genarrative-response-envelope自动在“裸数据 / 标准 envelope / legacy error + meta”之间切换。meta.apiVersion、meta.requestId、meta.routeVersion、meta.operation、meta.latencyMs、meta.timestamp已按当前前端契约生成,响应头回写仍留给后续独立任务。
当前基础响应头约定:
- 所有响应都会回写
x-request-id。 - 所有响应都会回写固定的
x-api-version,值来自shared_contracts::api::API_VERSION,当前为2026-06-16,并与 bodymeta.apiVersion保持一致。 - 所有响应都会回写
x-route-version,当前阶段默认与x-api-version保持一致,后续再按路由粒度细分。 - 所有响应都会回写
x-response-time-ms,值来源于RequestContext内记录的请求开始时间。
当前 /healthz 约定:
- 路径固定为
/healthz。 - 裸响应继续返回
{ ok: true, service: "genarrative-node-server" },保持与当前 Node 工程兼容。 - 当请求携带
x-genarrative-response-envelope时,/healthz会返回标准 success envelope。 x-request-id、x-api-version、x-route-version、x-response-time-ms会在/healthz响应中一并回写。
当前本地检查链路约定:
../../scripts/check.ps1与../../scripts/check.sh统一串联cargo fmt --all --check、cargo clippy、cargo check、cargo test。- 默认检查整个
server-rsworkspace,确保后续多 crate 扩容时仍然保持统一口径。 - 当只需聚焦单个 crate 时,可通过
-Package或SERVER_RS_CHECK_PACKAGE收窄clippy / check / test目标。 cargo fmt --all --check仍固定覆盖整个 workspace,避免多 crate 下格式基线漂移。
当前本地 smoke 链路约定:
../../scripts/smoke.ps1与../../scripts/smoke.sh会先构建api-server,再拉起临时本地进程完成冒烟验证。- smoke 当前固定校验
/healthz的 raw 响应、envelope 响应以及x-request-id、x-api-version、x-route-version、x-response-time-ms头。 - smoke 通过后,可作为“Axum 服务可独立启动且基础 contract 可联通”的本地自动化证据。
3. 边界约束
api-server负责 HTTP、SSE、Cookie、Header、路由与协议装配。- 业务逻辑优先通过独立模块 crate 暴露能力,再由主工程组合。
- 外部副作用通过
platform-auth、platform-oss、platform-llm与各模块 crate 的应用层完成。 - 不把领域规则直接堆在 handler 中。
- 当前密码登录由
module-auth负责用例编排,api-server只负责请求解析、JWT 签发与 refresh cookie 写回。 - 当前
/api/auth/me复用现有 Bearer JWT 中间件与module-auth用户快照查询,不直接绕过模块边界读取内部状态。 - 当前
/api/auth/refresh复用module-auth的 refresh session 轮换能力,api-server负责 refresh cookie 读取、失败清理与 access token 重签。 - 当前
/api/auth/logout复用module-auth的当前会话吊销与用户版本递增能力,api-server负责 Bearer JWT、refresh cookie 读取与清理 cookie 回写。 - 当前
/api/assets/objects/confirm先由platform-oss完成私有HEAD Object校验,再通过spacetime-client调用spacetime-module的对象确认持久化入口。 - 当前
/api/assets/objects/bind只绑定已确认对象到业务实体槽位,不访问 OSS,不创建悬空asset_object_id。 - 当前手机号登录与微信登录都复用
module-auth的进程内认证仓储,api-server负责请求解析、场景判定、系统 JWT 签发与 refresh cookie 写回。 - 当前微信回调不会把第三方 token 直接透传给前端或 SpacetimeDB,而是统一换成系统签发的 JWT。
- 当前
/api/assets/sts-upload-credentials按“服务器上传、Web 只下载”口径固定返回403,不向浏览器下发 OSS 写权限。 - 当前
/api/assets/character-visual/*第一批只保证现役接口 contract、OSS 草稿/正式对象、asset_object与asset_entity_binding主链可用;真实图片模型、workflow cache 与本地角色覆盖写回仍在后续阶段。 - 当前
/api/assets/character-animation/import-video第一批只接受data:video/*;base64,...并写入 OSS 草稿区,不读取旧本地public/路径,也不创建正式asset_object。 - 当前
/api/assets/character-workflow-cache/*第一批只把工作流 JSON 草稿写入 OSS,不迁移历史本地缓存,也不创建正式asset_object。 - 当前
/api/assets/character-animation/generate第一批只用 Rust 占位产物打通AiTaskService + OSS草稿链;image-sequence写 SVG 帧,视频类策略优先复用参考视频或仓库内可播放占位视频,不代表真实上游视频模型已完成迁移。 - 当前
/api/assets/character-animation/publish会把前端提交帧、动作级 manifest 与总 manifest 写入 OSS,并只把总 manifest 确认为asset_object后绑定到character / animation_set。 /generated-*只作为legacyPublicPath/ OSS object key 标识,读取必须通过/api/assets/read-url或业务投影中的签名读 URL。