docs: add bark battle backend ddd plan

This commit is contained in:
2026-05-11 15:52:20 +08:00
parent 2b6087de4c
commit 2ca096f821
2 changed files with 800 additions and 0 deletions

View File

@@ -0,0 +1,799 @@
# bark-battle 后端 DDD 技术方案2026-05-11
## 1. 背景、范围与非目标
### 1.1 背景
`bark-battle` / “汪汪声浪大作战”是一个浏览器 2D 声控狗叫对战玩法。玩家通过麦克风发出狗叫声,浏览器 runtime 根据音量峰值、有效叫声次数与节奏推动顶部红蓝能量条;每局默认 30 秒;结束后按能量条偏向判定胜负或平局。
现有前端方案 `docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md` 已覆盖 Phaser / TypeScript / Vite / Web Audio / DOM HUD 的 runtime 落地方式,并明确不覆盖后端表结构、成绩持久化、作品发布、广场接入与实时多人协议。因此需要单独补充后端 DDD 技术方案,避免前端 runtime 在接入平台作品、正式游玩埋点、成绩、排行榜和发布闭环时承接不属于表现层的业务真相。
本方案遵循当前 Genarrative 后端路线:`server-rs` + Axum + SpacetimeDB。DDD 边界保持为:
- `module-*`:纯领域规则与 use case 约束。
- `spacetime-module`SpacetimeDB 表、reducer、migration。
- `spacetime-client`SpacetimeDB 绑定调用 facade。
- `api-server`HTTP / SSE / BFF 门面与权限校验入口。
- `shared-contracts`:前后端共享 DTO、请求、响应、错误码与 schema 约束。
- `platform-*`:作品、发布、广场、埋点等平台能力的领域边界。
### 1.2 本文范围
本文覆盖后端方案,不实现代码:
1. bark-battle 玩法接入级别建议。
2. 后端 DDD 分层与职责边界。
3. shared contracts 草案。
4. SpacetimeDB 数据模型草案。
5. HTTP API / facade 草案。
6. SpacetimeDB migration 与绑定生成策略。
7. 安全、隐私与反作弊约束。
8. TDD / 验收顺序与可执行命令。
9. 与现有前端方案和 BDD 文档的关系。
### 1.3 非目标
MVP 明确不做:
- 不保存原始麦克风音频、音频片段、可还原语音内容的 waveform 或频谱明细。
- 不做实时多人在线对战;首版只支持本地 runtime + 后端记录派生结果。
- 不做复杂 AI 声纹识别、狗叫语义识别、身份声纹比对或真人/动物声纹分类。
- 不由前端直接写正式成绩、排行榜或作品发布状态。
- 不把 Phaser / Web Audio / DOM HUD 逻辑迁入后端。
- 不在本方案中实现代码、建表或生成绑定。
## 2. 玩法接入级别建议
### 2.1 推荐首版闭环
建议先支持“本地 runtime + 可发布配置化作品 + 单局结果记录 / 可选排行榜”的闭环:
1. 创作者创建 bark-battle 草稿配置标题、描述、狗狗主题、背景、难度、单局时长、音量阈值、AI 对手参数和排行榜开关。
2. 发布为稳定作品 ID`playTypeId = "bark-battle"`
3. 玩家从作品页或广场进入 runtime前端获取发布态 runtime config。
4. 玩家授权麦克风后在本地完成 30 秒声控对战。
5. 前端提交单局 finish 请求,只上传派生指标,例如峰值、有效叫声次数、节奏命中、最终能量、客户端结果摘要等。
6. 后端校验 work、config version、run token、时长、分数范围和权限后生成服务端认可的 run result / score summary。
7. 若作品开启排行榜,则写入可投影的 leaderboard 记录。
8. 正式作品级游玩埋点统一写 `work_play_start`,其中 `scope_kind=work``scope_id=稳定作品 ID`metadata 包含 `playType``workId``sourceRoute``userId`
### 2.2 后续增强路径
后续再考虑多人实时:
- Phase 2排行榜、挑战分享、个人历史成绩、作品统计面板。
- Phase 3异步影子对手 / ghost replay但仍不保存原始音频只保存低维派生曲线或聚合指标。
- Phase 4实时多人对战协议需要独立同步模型、房间服务、延迟补偿、断线恢复与更严格反作弊不应混入 MVP。
## 3. DDD 分层设计
### 3.1 总体分层
```text
frontend/runtime
-> api-server HTTP BFF
-> shared-contracts DTO
-> spacetime-client facade
-> generated SpacetimeDB bindings
-> spacetime-module reducers / tables / migration.rs
-> module-bark-battle pure domain
-> platform-work / platform-publish / platform-tracking / platform-leaderboard
```
### 3.2 `module-bark-battle` 职责
建议新增 `server-rs/crates/module-bark-battle/`,只放纯领域规则,不依赖 Axum、SpacetimeDB SDK、HTTP、数据库绑定或前端类型。
职责:
- 校验 bark-battle 配置合法性。
- 定义配置版本兼容规则。
- 计算提交结果的派生分数区间与胜负判定是否自洽。
- 计算 `ScoreSummary`、排行榜排序分数、统计指标。
- 定义反作弊基础规则时长范围、有效叫声次数上限、峰值范围、能量范围、提交窗口、run 状态机。
不职责:
- 不访问数据库。
- 不处理 HTTP 请求。
- 不生成 SpacetimeDB 表。
- 不处理麦克风音频采样。
### 3.3 `shared-contracts` 职责
建议新增 `server-rs/crates/shared-contracts/src/bark_battle.rs`,并在前端共享契约生成流程中对齐同名 DTO。
职责:
- 定义草稿、发布态 runtime config、work summary、run start、run finish、run result、score summary、leaderboard DTO。
- 定义 request / response / error code。
- 保持字段命名、枚举值、时间单位和数值范围稳定。
约束:
- DTO 可以表达业务数据,但不承载领域算法。
- 前端不得手写与后端不一致的正式契约;如果存在 TypeScript mirror需要由契约生成或测试保证一致。
### 3.4 `spacetime-module` 职责
建议在现有 SpacetimeDB 模块边界内新增 bark-battle 表与 reducer或按当前仓库约定新增独立模块文件。职责
- 定义表作品配置、发布版本、runtime run、score/stat、leaderboard entry。
- 定义 reducer / procedure保存草稿、发布版本、开始 run、结束 run、写排行榜、查询投影所需索引。
- 维护 migration。
必须明确:
- 所有表结构变更进入 `migration.rs`
- SpacetimeDB 绑定通过既有生成命令生成。
- 不手改生成物,不手改 generated bindings。
### 3.5 `spacetime-client` 职责
职责:
- 封装 generated bindings`api-server` 提供稳定 facade。
- 隐藏 reducer 名称、表订阅细节和绑定类型差异。
- 将 SpacetimeDB 错误转换为后端内部错误模型。
不职责:
- 不放业务规则主逻辑。
- 不绕过 `module-bark-battle` 做胜负和分数裁决。
### 3.6 `api-server` 职责
Axum HTTP / BFF 门面职责:
- 鉴权、用户上下文、work 权限、发布态读取权限。
- 解析请求、调用 domain 校验、调用 spacetime-client facade。
- 将内部错误映射成 HTTP status + shared error code。
- 负责正式作品级游玩埋点入口,统一写 `work_play_start`
- 为前端 runtime 提供一次性 start token / run id避免匿名 finish 直接刷榜。
### 3.7 `platform-*` 职责
- `platform-work`:稳定作品 ID、作品所有权、作品摘要、作品状态。
- `platform-publish`草稿到发布态版本、config version、发布可见性。
- `platform-tracking`:统一埋点,尤其 `work_play_start`
- `platform-leaderboard`若已有通用排行榜能力bark-battle 只提供 score projection不重复建设平台级排名系统。
### 3.8 `frontend/runtime` 职责边界
前端只做:
- Phaser / DOM HUD 表现。
- Web Audio 采样、环境噪声校准和本地即时反馈。
- 本地临时 UI 状态:权限、倒计时、动画、结算展示。
- 调用 start / finish / leaderboard API。
前端不得承接正式业务真相:
- 不直接决定正式排行榜结果。
- 不直接写作品发布状态。
- 不绕过后端写成绩。
- 不上传原始麦克风音频。
## 4. shared contracts 设计草案
以下为字段草案,具体 Rust / TypeScript 命名按仓库契约规范落地。
### 4.1 BarkBattleDraft
```text
BarkBattleDraft {
draftId: string
ownerUserId: string
playTypeId: "bark-battle"
title: string
description?: string
theme: BarkBattleTheme
runtimeConfig: BarkBattleRuntimeConfigDraft
leaderboardEnabled: boolean
visibility: "private" | "unlisted" | "public"
createdAt: string
updatedAt: string
}
```
### 4.2 BarkBattleRuntimeConfig
```text
BarkBattleRuntimeConfig {
workId: string
configVersion: number
playTypeId: "bark-battle"
durationMs: number // MVP 默认 30000
energyMin: number // 默认 -100
energyMax: number // 默认 100
winEnergyThreshold: number // 可选:低于阈值可平局
barkThreshold: number // 归一化 0..1
peakWeight: number
barkCountWeight: number
rhythmWeight: number
opponent: {
difficulty: "easy" | "normal" | "hard"
basePower: number
variance: number
}
theme: {
playerDogSkin: string
opponentDogSkin: string
stageId: string
soundPackId?: string
}
leaderboardEnabled: boolean
publishedAt: string
}
```
### 4.3 WorkSummary
```text
BarkBattleWorkSummary {
workId: string
playTypeId: "bark-battle"
title: string
description?: string
coverAssetId?: string
authorUserId: string
authorDisplayName?: string
configVersion: number
leaderboardEnabled: boolean
totalPlayCount: number
publishedAt: string
updatedAt: string
}
```
### 4.4 RunStart
```text
BarkBattleRunStartRequest {
workId: string
configVersion: number
sourceRoute?: string
clientRuntimeVersion?: string
}
BarkBattleRunStartResponse {
runId: string
runToken: string
workId: string
configVersion: number
serverStartedAt: string
expiresAt: string
runtimeConfig: BarkBattleRuntimeConfig
}
```
### 4.5 RunFinish
```text
BarkBattleRunFinishRequest {
runId: string
runToken: string
workId: string
configVersion: number
clientStartedAt?: string
clientFinishedAt?: string
elapsedMs: number
finalEnergy: number
clientWinner: "player" | "opponent" | "draw"
metrics: BarkBattleDerivedMetrics
clientRuntimeVersion?: string
}
BarkBattleDerivedMetrics {
peakVolumeMax: number // 0..1
peakVolumeAvg: number // 0..1
validBarkCount: number
rhythmHitCount: number
longestCombo: number
sampleWindowCount?: number
calibrationNoiseFloor?: number // 0..1
}
```
### 4.6 RunResult
```text
BarkBattleRunResult {
runId: string
workId: string
userId?: string
configVersion: number
accepted: boolean
serverWinner: "player" | "opponent" | "draw"
finalEnergy: number
score: number
scoreSummary: BarkBattleScoreSummary
leaderboardEntry?: BarkBattleLeaderboardEntry
antiCheatFlags: string[]
finishedAt: string
}
```
### 4.7 ScoreSummary
```text
BarkBattleScoreSummary {
score: number
grade: "S" | "A" | "B" | "C" | "D"
finalEnergy: number
winMargin: number
validBarkCount: number
peakVolumeMax: number
rhythmHitCount: number
longestCombo: number
elapsedMs: number
}
```
### 4.8 Leaderboard 可选类型
```text
BarkBattleLeaderboardQuery {
workId: string
configVersion?: number
period: "all" | "daily" | "weekly"
limit: number
cursor?: string
}
BarkBattleLeaderboardEntry {
rank?: number
runId: string
workId: string
userId?: string
displayName?: string
score: number
scoreSummary: BarkBattleScoreSummary
createdAt: string
}
BarkBattleLeaderboardResponse {
workId: string
entries: BarkBattleLeaderboardEntry[]
viewerBest?: BarkBattleLeaderboardEntry
nextCursor?: string
}
```
## 5. 数据模型草案
### 5.1 作品配置表
建议表:`bark_battle_work_config`
字段草案:
- `work_id`:稳定作品 ID关联平台作品。
- `draft_id`:草稿 ID可选。
- `owner_user_id`:创作者。
- `play_type_id`:固定 `bark-battle`
- `config_version`:发布配置版本。
- `title``description``cover_asset_id`
- `runtime_config_json`:发布态 runtime 配置 JSON字段需由 shared contracts 校验。
- `leaderboard_enabled`
- `status``draft` / `published` / `archived`
- `created_at``updated_at``published_at`
约束:
- 同一 `work_id + config_version` 不可变;新发布生成新版本。
- runtime 请求只读发布态配置。
### 5.2 runtime run 表
建议表:`bark_battle_runtime_run`
字段草案:
- `run_id`
- `run_token_hash`:保存 token hash不保存明文 token。
- `work_id`
- `config_version`
- `user_id`:匿名时可空或使用匿名会话 ID。
- `source_route`
- `status``started` / `finished` / `rejected` / `expired`
- `server_started_at``server_finished_at``expires_at`
- `client_elapsed_ms`
- `final_energy`
- `client_winner``server_winner`
- `anti_cheat_flags_json`
- `client_runtime_version`
### 5.3 score / stat 表
建议表:`bark_battle_score_record`
字段草案:
- `score_id`
- `run_id`
- `work_id`
- `config_version`
- `user_id`
- `score`
- `grade`
- `final_energy`
- `valid_bark_count`
- `peak_volume_max`
- `peak_volume_avg`
- `rhythm_hit_count`
- `longest_combo`
- `elapsed_ms`
- `metrics_json`:只保存派生聚合指标。
- `created_at`
明确禁止:
- 不保存原始麦克风音频。
- 不保存可还原语音的 PCM、Opus、MP3、WAV、base64 音频、逐帧 waveform。
- 不保存高精度声纹向量。
### 5.4 leaderboard 表
若平台已有通用排行榜,优先复用平台 leaderboard 投影;否则可新增 `bark_battle_leaderboard_entry`
- `entry_id`
- `work_id`
- `config_version`
- `run_id`
- `user_id`
- `score`
- `tie_breaker_energy`
- `tie_breaker_elapsed_ms`
- `created_at`
排序建议:
1. `score` 降序。
2. `final_energy` / `winMargin` 降序。
3. `elapsed_ms` 更接近配置时长者优先,避免异常短局刷分。
4. `created_at` 升序或按平台既有规则。
## 6. API 草案
路径仅为草案,落地时按 `api-server` 当前路由命名规范调整。
### 6.1 创建 / 保存草稿
```text
POST /api/bark-battle/drafts
PUT /api/bark-battle/drafts/{draftId}
GET /api/bark-battle/drafts/{draftId}
```
职责:
- 仅创作者可创建和保存。
- 校验 `playTypeId = bark-battle`
- 调用 `module-bark-battle` 校验 runtime config 范围。
### 6.2 发布 / 获取作品
```text
POST /api/bark-battle/drafts/{draftId}/publish
GET /api/works/{workId}/bark-battle
GET /api/bark-battle/works/{workId}/runtime-config
```
职责:
- 发布生成稳定 `workId` 和递增 `configVersion`
- 获取作品只返回发布态配置与展示摘要。
- 未发布或无权限作品返回明确错误。
### 6.3 start runtime
```text
POST /api/bark-battle/runs/start
```
请求:`BarkBattleRunStartRequest`。响应:`BarkBattleRunStartResponse`
职责:
- 校验作品存在、发布态、可游玩。
- 校验 config version必要时返回最新版本。
- 创建 `run_id` 与一次性 `run_token`
- 写正式作品级游玩埋点:`work_play_start`
埋点要求:
```text
event_key: work_play_start
scope_kind: work
scope_id: <稳定作品 ID>
metadata: {
playType: "bark-battle",
workId: "<workId>",
sourceRoute: "<sourceRoute>",
userId: "<userId or anonymous>"
}
```
### 6.4 finish runtime
```text
POST /api/bark-battle/runs/{runId}/finish
```
请求:`BarkBattleRunFinishRequest`。响应:`BarkBattleRunResult`
职责:
- 校验 run token。
- 校验 run 仍处于 `started` 且未过期。
- 校验 `work_id + config_version` 与 start 时一致。
- 校验时长、finalEnergy、metrics 范围。
- 使用 `module-bark-battle` 生成服务端认可的 `serverWinner``score``ScoreSummary``antiCheatFlags`
-`bark_battle_runtime_run` finish 状态与 `bark_battle_score_record`
- 如开启 leaderboard 且结果 accepted写排行榜。
### 6.5 作品级游玩埋点
`start runtime` 内部必须触发统一埋点;不建议前端单独调用一个 bark-battle 专用埋点 API。若平台已有通用 tracking API则 api-server 内部调用 platform tracking facade
```text
track_event(
event_key = "work_play_start",
scope_kind = "work",
scope_id = workId,
metadata = { playType, workId, sourceRoute, userId }
)
```
### 6.6 可选排行榜
```text
GET /api/bark-battle/works/{workId}/leaderboard?period=all&limit=50&cursor=...
GET /api/bark-battle/works/{workId}/leaderboard/me
```
职责:
- 只读已接受成绩。
- 支持分页。
- 支持匿名用户时隐藏或弱化身份展示。
- 若作品关闭排行榜,返回空投影或明确 disabled 状态。
## 7. SpacetimeDB 与 migration 策略
### 7.1 表 / reducer / procedure 边界
SpacetimeDB 侧只承载持久化、索引、reducer 原子写入和可查询投影,不承载 HTTP 鉴权或前端表现。
建议 reducer / procedure
- `bark_battle_save_draft_config`:保存草稿配置。
- `bark_battle_publish_work_config`:发布配置版本。
- `bark_battle_start_run`:创建 runtime run。
- `bark_battle_finish_run`:结束 run 并写 score。
- `bark_battle_upsert_leaderboard_entry`:写排行榜投影。
- `bark_battle_get_work_runtime_config`:读取发布态配置。
- `bark_battle_get_leaderboard`:读取排行榜投影。
如当前架构要求 reducer 仅由 `spacetime-client` 调用,则 api-server 不直接操作 SpacetimeDB SDK。
### 7.2 migration.rs
所有表结构变更必须进入 `migration.rs`
- 新增 bark-battle 表时写显式 migration。
- 新增索引、唯一约束或版本字段时写 migration。
- 从草稿 JSON 拆字段时写数据迁移说明。
- 不允许只改 Rust struct 而不补 migration。
### 7.3 绑定生成
涉及 SpacetimeDB schema / reducer 变更后:
1. 运行仓库既有 SpacetimeDB 绑定生成命令。
2. 检查 generated bindings 变化。
3. `spacetime-client` 只引用生成物,不手改生成物。
4. shared contracts 与 generated bindings 的差异通过 facade 消化,不让前端直接依赖数据库绑定。
明确要求:不手改生成物,不手改 generated bindings不用临时复制粘贴类型绕过生成流程。
### 7.4 api-server facade
`api-server` 通过 `spacetime-client` facade 调用 SpacetimeDB
```text
BarkBattleService
-> BarkBattleDomainPolicy
-> BarkBattleSpacetimeClient
-> generated bindings
```
这样可以保证:
- HTTP 层易测试。
- domain 纯函数可独立测试。
- SpacetimeDB 绑定变更不会扩散到 route handler。
## 8. 安全、隐私与反作弊
### 8.1 隐私
- 不上传原始音频。
- 不保存原始音频。
- 不保存可还原用户声音的高精度采样曲线。
- 只保存派生指标:峰值、均值、有效叫声次数、节奏命中、最终能量、分数、耗时。
- 前端权限文案必须说明麦克风只用于本地玩法输入MVP 不上传原始声音。
### 8.2 不信任前端胜负
后端不能直接信任:
- `clientWinner`
- `score`
- `finalEnergy`
- `elapsedMs`
- `validBarkCount`
后端必须校验并重算服务端认可结果。MVP 因不上传音频,无法完全证明声音真实性,但仍需做边界反作弊。
### 8.3 校验规则
必须校验:
- run token 是否匹配且未使用。
- run 是否未过期。
- `work_id + config_version` 是否与 start 时一致。
- 用户是否有权限游玩该 work。
- 提交时长是否接近配置时长,例如 30 秒局允许少量网络 / 页面调度误差。
- `finalEnergy` 是否在配置范围。
- `peakVolumeMax``peakVolumeAvg` 是否在 `0..1`
- `validBarkCount``rhythmHitCount``longestCombo` 是否在物理合理上限。
- `clientStartedAt` / `clientFinishedAt` 与服务端时间窗口是否合理。
- 同一用户 / 匿名会话的频率限制。
### 8.4 反作弊处理
建议结果状态:
- `accepted`:写 score可进入排行榜。
- `accepted_with_flags`:写 score但标记异常默认不入榜或降低可信度。
- `rejected`:不入榜,只记录 run 失败原因。
常见 flags
- `elapsed_too_short`
- `elapsed_too_long`
- `metric_out_of_range`
- `config_version_mismatch`
- `token_invalid`
- `duplicate_finish`
- `rate_limited`
- `impossible_bark_count`
## 9. TDD / 验收顺序与命令
本任务只写方案,不执行代码实现。后续落地建议按以下顺序:
### 9.1 domain 纯函数测试
先实现 `module-bark-battle`
```bash
cd server-rs
cargo test -p module-bark-battle
```
测试覆盖:
- runtime config 校验。
- finish metrics 范围校验。
- 胜负判定。
- score / grade / leaderboard score 计算。
- 反作弊 flags。
### 9.2 contracts 测试
再实现 shared contracts
```bash
cd server-rs
cargo test -p shared-contracts bark_battle
cargo check -p shared-contracts
```
验收:
- DTO 可序列化 / 反序列化。
- 枚举值稳定。
- 可选字段向后兼容。
- TypeScript mirror 或契约生成产物与 Rust contract 对齐。
### 9.3 SpacetimeDB / api-server check
实现表、reducer、migration 与 facade 后:
```bash
cd server-rs
cargo check -p spacetime-module
cargo check -p spacetime-client
cargo check -p api-server
cargo test -p api-server bark_battle
```
如仓库有统一命令,以统一命令为准,例如:
```bash
cd server-rs
cargo test --workspace
```
验收:
- migration.rs 包含新增表与变更。
- 绑定由生成命令产出,未手改生成物。
- api-server route handler 只做编排,不内嵌复杂计分规则。
### 9.4 前端 contract 对齐
前端只在后端 contract 稳定后接入:
```bash
npm run typecheck
npm test -- bark-battle
npm run build
```
验收:
- runtime start / finish 请求字段与 shared contracts 一致。
- 前端 result panel 展示后端 `RunResult`
- 前端本地结算只作为即时反馈,正式结果以后端返回为准。
### 9.5 手工验收清单
- 可以创建并保存 bark-battle 草稿。
- 可以发布成稳定作品 ID`playTypeId = bark-battle`
- runtime start 返回 config、runId、runToken。
- start 写入 `work_play_start`scope 与 metadata 符合要求。
- finish 不上传音频,只上传派生指标。
- finish 返回服务端认可的 result。
- 异常时长、重复提交、config version mismatch 会被拒绝或打 flag。
- 排行榜关闭时不写榜;开启时只写 accepted 结果。
## 10. 与现有前端方案和 BDD 文档的关系
### 10.1 依赖文档
- 前端 runtime 方案:`docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md`
- BDD / DDD / TDD 总计划:`.hermes/plans/2026-05-11_144229-bark-battle-2d-game-bdd-ddd-tdd-plan.md`
- 当前后端实现基线:`docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
- SpacetimeDB 表结构变更约束:`docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md`
### 10.2 与前端方案的对齐点
- 前端方案负责 Phaser / Web Audio / DOM HUD本文负责作品、成绩、排行榜、发布和埋点。
- 前端 `BarkBattleSnapshot` 可用于本地即时表现,但正式 `RunResult` 以后端返回为准。
- 前端不上传原始音频,只上传 `BarkBattleDerivedMetrics`
- 前端本地 config 应来自后端发布态 `BarkBattleRuntimeConfig`,不能在生产游玩中使用未发布临时配置。
- 前端 result panel 应能展示后端返回的 score、grade、antiCheatFlags 与 leaderboard entry。
### 10.3 与 BDD 的对齐点
后续 BDD 场景应覆盖:
- 玩家从作品页进入 bark-battle runtime。
- 玩家授权麦克风后开始 30 秒对战。
- 玩家完成单局后看到后端确认结果。
- 未授权麦克风时可以看到降级说明,但不写正式成绩。
- 作品关闭排行榜时不展示排名入口。
- 作品开启排行榜时展示当前作品排名。
- 重复 finish / 过期 run / 配置版本不一致时返回可解释错误。
### 10.4 后端落地顺序建议
1. 先只做 contract + domain固定 `playTypeId = bark-battle` 与配置 schema。
2. 再做草稿 / 发布态作品配置读写。
3. 再做 start / finish run 与 `work_play_start` 埋点。
4. 最后做排行榜投影。
5. 实时多人协议另起方案,不与 MVP 混做。

View File

@@ -4,6 +4,7 @@
## 文档列表
- [BARK_BATTLE_BACKEND_DDD_TECHNICAL_PLAN_2026-05-11.md](./BARK_BATTLE_BACKEND_DDD_TECHNICAL_PLAN_2026-05-11.md):冻结“汪汪声浪大作战 / bark-battle”后端 DDD 技术方案,明确 `server-rs + Axum + SpacetimeDB` 分层边界、shared contracts、作品配置、runtime run、派生成绩、排行榜、`work_play_start` 埋点、migration/绑定生成策略,以及不保存原始麦克风音频的隐私与反作弊约束。
- [BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md](./BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md):冻结“汪汪声浪大作战 / bark-battle”2D 浏览器 runtime 技术方案,明确 Phaser + TypeScript + Vite 选型、纯 TS simulation 与 Phaser renderer/DOM HUD 边界、Web Audio 输入适配、移动端权限降级和后续测试验证命令。
- [CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md](./CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md):冻结儿童动作识别互动玩法 Demo 固定热身关的开发落地规格,覆盖横屏展示、摄像头背景虚化、角色剪影、绿色圆环 2 秒保持、动作教学、当前会话内空间边界记录和后续关卡安全暂停规则。
- [RUNTIME_INPUT_DEVICE_ABSTRACTION_2026-05-10.md](./RUNTIME_INPUT_DEVICE_ABSTRACTION_2026-05-10.md)记录运行态输入设备抽象层明确鼠标、触控、mocap 等设备统一归一为通用拖拽语义,玩法组件只负责解释目标和落点。