45 KiB
Technical Design Document
绘境AI生态平台MVP Technical Design Document
Product Overview
Context for the technical design.
本技术设计文档面向将要实现绘境AI生态平台MVP的工程团队,基于现有PRD目标,将“一句话AI生成轻量小游戏、游戏流即点即玩、创作者发布与基础数据反馈、运营审核与推荐管理”落地为可实施的系统架构、数据模型、接口设计、测试方案和部署方案。
MVP技术策略采用“模板约束生成 + Web运行容器 + 异步任务队列 + 规则推荐”的方案,优先保障端到端闭环稳定性,而不是追求完全开放式代码生成。生成结果以配置化游戏工程为主,通过统一运行时容器在Web端加载运行,便于性能控制、内容审核、埋点采集和后续扩展。
Purpose
-
解决的问题
- 非技术创作者无法将游戏创意快速转化为可试玩作品。
- 玩家发现轻量小游戏成本高,传统游戏分发依赖下载、安装和复杂选择。
- 平台早期需要验证AI创作供给、游戏流消费和数据反馈是否能形成生态闭环。
-
技术机会
- 使用大模型理解自然语言Prompt,并映射到受控玩法模板和参数配置。
- 使用Web小游戏运行容器实现即点即玩,降低分发门槛。
- 使用事件埋点和内容质量信号,为后续推荐和商业化提供数据基础。
- 使用内容安全检测与审核后台,降低UGC和AI生成内容的合规风险。
-
典型用户场景
- 创作者输入“做一个像素风太空躲避游戏,飞船躲避陨石并收集能量,坚持60秒获胜”,系统生成可预览小游戏,并允许编辑标题、封面和发布。
- 玩家进入首页后像刷短视频一样上下滑动试玩小游戏,支持点赞、收藏、分享和举报。
- 运营人员进入后台审核新发布游戏,试玩后执行通过、拒绝、下架或加入精选池。
- 团队通过数据看板查看生成成功率、游戏加载时间、试玩转化、互动率和举报率。
Target Audience
-
普通创作者 / 非技术用户
- 需求:无需编程、美术和引擎知识即可生成可玩游戏。
- 技术支持:Prompt输入、模板选择、异步生成进度、浏览器预览、保存草稿、发布到站内游戏流。
-
进阶UGC创作者 / 游戏达人
- 需求:快速批量产出轻量小游戏,观察数据并优化标题、封面、规则和标签。
- 技术支持:模板参数可调、版本覆盖更新、基础数据看板、分享链接和渠道参数。
-
玩家 / 轻量游戏消费者
- 需求:无需下载,低决策成本连续发现和试玩小游戏。
- 技术支持:移动优先游戏流、资源预加载、CDN加速、错误自动跳过、互动反馈。
-
平台运营人员
- 需求:控制内容质量、安全合规和冷启动推荐效果。
- 技术支持:审核队列、试玩预览、风险标记、精选池、曝光限制和操作日志。
-
系统管理员 / 工程团队
- 需求:监控生成任务、运行错误、服务健康度、权限边界和安全风险。
- 技术支持:结构化日志、指标看板、告警、RBAC、审计日志和回滚机制。
Expected Outcomes
-
短期业务结果
- MVP上线后8周内支持500名注册创作者。
- 至少100名创作者完成1款游戏发布。
- 累计上线300款可试玩小游戏。
- 玩家单次会话平均试玩不少于3款游戏。
-
技术结果
- 生成任务成功率不低于85%。
- 平台核心链路可用性不低于99%。
- 游戏流首屏可交互时间P75低于3秒,P95低于6秒。
- 游戏加载或运行阻断性错误率低于3%。
- 核心事件上报成功率不低于99%。
-
长期影响
- 为后续可视化编辑器、个性化推荐、广告分成、多渠道自动发布和素材市场建立可扩展架构。
- 沉淀Prompt、模板参数、互动行为和内容质量数据,用于优化生成质量和推荐策略。
Architecture
The structural design of the system.
High-Level Architecture
-
推荐技术栈
- Frontend:Next.js 14、React、TypeScript、Tailwind CSS、Zustand、React Query。
- Game Runtime:Phaser 3 + 自研Game SDK桥接层,优先支持2D轻量小游戏。
- Backend:NestJS、TypeScript、REST API,按模块化单体起步,预留服务拆分边界。
- Database:PostgreSQL 15,使用Prisma ORM管理Schema和Migration。
- Cache / Queue:Redis 7,BullMQ用于异步生成、审核、资源打包、事件聚合任务。
- Object Storage:阿里云OSS或AWS S3,存储封面、上传素材、生成素材和游戏包。
- CDN:阿里云CDN、CloudFront或Cloudflare,用于游戏资源、封面图和静态前端加速。
- Search / Analytics MVP:PostgreSQL聚合表 + ClickHouse可选;MVP先用PostgreSQL分区事件表,增长后迁移ClickHouse。
- Auth:JWT + Refresh Token,匿名游客使用anonymous_id Cookie / localStorage标识。
- Observability:OpenTelemetry、Prometheus、Grafana、Sentry、Loki或云日志服务。
-
主要组件
-
Web App
- 创作工作台:Prompt输入、模板选择、生成状态、预览、发布。
- 玩家游戏流:游戏卡片、预加载、滑动切换、互动、举报。
- 创作者后台:我的游戏、数据概览、草稿和发布状态。
- 运营后台:审核、试玩、推荐池、下架、用户权限。
-
API Server
- 账号与权限模块。
- 游戏与版本管理模块。
- 生成任务模块。
- 发布与审核模块。
- 游戏流推荐模块。
- 互动与埋点模块。
- 文件上传与资源签名模块。
-
Generation Worker
- 接收Prompt生成任务。
- 调用LLM解析游戏意图。
- 选择玩法模板并生成GameConfig。
- 调用素材生成服务或使用内置素材库。
- 打包游戏资源并输出可运行Manifest。
-
Moderation Worker
- 检测Prompt、标题、简介、封面和上传素材。
- 输出风险等级、命中策略和审核建议。
-
Event Worker
- 批量消费前端埋点。
- 写入事件表并更新聚合指标。
-
Recommendation Service
- MVP为规则策略,可在API Server内实现。
- 根据精选池、新发布、质量分、用户互动和加载错误率返回游戏列表。
-
-
通信协议
- 前端与后端:REST over HTTPS。
- 生成任务状态:优先Server-Sent Events或轮询;MVP可使用2秒轮询,后续升级WebSocket。
- Worker任务:BullMQ over Redis。
- 静态资源:HTTPS + CDN。
- 第三方AI服务:HTTPS API。
-
设计模式
- Modular Monolith:MVP阶段降低部署和运维复杂度,同时保持模块边界。
- Event-driven:生成、审核、发布、互动、埋点和指标聚合使用事件驱动。
- CQRS Lite:写入操作走业务表,读取高频的游戏流和数据看板使用聚合表或缓存。
- State Machine:GenerationTask、Game、ReviewRecord采用明确状态机,避免状态混乱。
Data Structures & Algorithms
-
核心数据结构
-
GameConfig
- JSON结构,描述玩法模板、参数、关卡、角色、素材、胜负条件和UI文案。
- 选择理由:便于受控生成、版本管理、Web运行时加载和安全校验。
-
GameManifest
- JSON结构,描述运行入口、资源列表、版本号、校验hash、SDK版本和预加载策略。
- 选择理由:前端游戏容器可根据Manifest统一加载不同游戏。
-
FeedItem
- 包含game_id、creator_id、score、reason、preload_assets、interaction_state。
- 选择理由:解耦推荐计算和前端展示。
-
EventPayload
- 标准化埋点结构:event_name、user_id、anonymous_id、game_id、session_id、timestamp、properties。
- 选择理由:便于漏斗、留存和内容质量分析。
-
-
GameConfig示例
{
"template": "avoidance_v1",
"theme": "pixel_space",
"durationSeconds": 60,
"player": {
"sprite": "ship_blue",
"speed": 320,
"hitPoints": 3
},
"objectives": \[
{ "type": "survive", "seconds": 60 },
{ "type": "collect", "item": "energy", "target": 20 }
\],
"enemies": \[
{ "type": "asteroid", "spawnRatePerSecond": 1.2, "speedRange": \[120, 260\] }
\],
"controls": {
"mobile": "drag",
"desktop": "arrow_keys"
},
"winCondition": "survive_and_collect",
"loseCondition": "hp_zero"
}
-
关键算法
-
Prompt到模板映射
- 输入:用户Prompt、用户选择模板、风格标签。
- 输出:template_id、confidence、normalized_parameters。
- MVP实现:LLM分类 + 规则兜底。
- 复杂度:O(T),T为模板数量,MVP模板数量小于10,性能可忽略。
-
游戏配置校验
- 输入:GameConfig。
- 输出:validated_config或错误列表。
- 规则:数值范围、必填字段、资源引用、关卡长度、资源体积、敏感词。
- 复杂度:O(N),N为配置节点数。
-
游戏流排序
- MVP评分公式:score = base_weight + recency_score + quality_score + interaction_score + creator_boost - risk_penalty - error_penalty。
- 冷启动权重:精选池、最新发布、每个新作保底曝光。
- 复杂度:候选集过滤O(N),排序O(N log N)。N通过分页候选集控制在200以内。
-
内容质量分
- quality_score基于试玩完成率、30秒留存、点赞率、收藏率、举报率、加载失败率。
- 每小时或每15分钟由Event Worker聚合更新。
-
-
扩展与性能考虑
- 生成任务使用队列削峰,避免LLM和打包服务阻塞主API。
- 游戏资源限制MVP单包不超过10MB,首屏关键资源不超过2MB。
- 热门游戏Manifest和元数据缓存到Redis,TTL 60至300秒。
- 游戏资源文件使用hash命名,启用长期CDN缓存。
- 埋点批量上报,前端每10条或5秒flush一次,避免影响游戏帧率。
System Interfaces
- API endpoints
| Method | Route | Purpose | Auth |
|---|---|---|---|
| POST | /api/v1/auth/login | 登录并返回访问令牌 | Public |
| POST | /api/v1/auth/refresh | 刷新访问令牌 | Refresh Token |
| GET | /api/v1/me | 获取当前用户资料与角色 | User |
| POST | /api/v1/generation/tasks | 创建AI生成任务 | Creator |
| GET | /api/v1/generation/tasks/{taskId} | 查询生成任务状态 | Creator |
| POST | /api/v1/games | 从生成结果创建游戏草稿 | Creator |
| GET | /api/v1/games/{gameId} | 获取游戏详情 | Public/Owner |
| PATCH | /api/v1/games/{gameId} | 更新标题、简介、封面、标签和参数 | Owner |
| POST | /api/v1/games/{gameId}/publish | 提交发布 | Owner |
| GET | /api/v1/feed | 获取游戏流列表 | Public |
| POST | /api/v1/interactions | 点赞、收藏、分享、举报 | User |
| POST | /api/v1/events/batch | 批量上报埋点事件 | Public |
| GET | /api/v1/creator/games | 获取创作者游戏列表 | Creator |
| GET | /api/v1/creator/games/{gameId}/stats | 获取单游戏数据看板 | Owner |
| GET | /api/v1/admin/reviews | 获取审核队列 | Operator |
| POST | /api/v1/admin/reviews/{reviewId}/decision | 审核通过、拒绝或下架 | Operator |
| POST | /api/v1/admin/featured-games | 加入精选池 | Operator |
- 创建生成任务请求示例
{
"prompt": "做一个像素风太空躲避游戏,玩家控制飞船躲避陨石,收集能量块,坚持60秒获胜。",
"templateHint": "avoidance",
"styleTags": \["pixel", "space"\],
"uploadedAssetIds": \["asset_01HXYZ"\]
}
- 创建生成任务响应示例
{
"taskId": "gt_01HZA9Z9H4Q7",
"status": "queued",
"estimatedSeconds": 90,
"pollingIntervalMs": 2000
}
- 查询生成任务响应示例
{
"taskId": "gt_01HZA9Z9H4Q7",
"status": "succeeded",
"progress": 100,
"currentStep": "preview_ready",
"gameDraft": {
"gameId": "game_01HZAA1M0KQ8",
"buildId": "build_01HZAA1R9QA3",
"previewUrl": "https://cdn.example.com/games/build_01HZAA1R9QA3/index.html"
},
"error": null
}
- 获取游戏流请求示例
GET /api/v1/feed?cursor=eyJzY29yZSI6MTIzfQ&limit=10&device=mobile
Authorization: Bearer optional
- 获取游戏流响应示例
{
"items": \[
{
"gameId": "game_01HZAA1M0KQ8",
"title": "像素太空逃亡",
"description": "躲避陨石并收集能量,坚持60秒。",
"coverUrl": "https://cdn.example.com/covers/game_01HZAA1M0KQ8.webp",
"creator": {
"userId": "user_123",
"nickname": "小林"
},
"manifestUrl": "https://cdn.example.com/manifests/build_01HZAA1R9QA3.json",
"preloadAssets": \[
"https://cdn.example.com/assets/ship.webp",
"https://cdn.example.com/assets/bg.webp"
\],
"interactionState": {
"liked": false,
"favorited": false
},
"reason": "featured_and_new"
}
\],
"nextCursor": "eyJzY29yZSI6MTE5fQ"
}
- 批量埋点请求示例
{
"sessionId": "sess_01HZAB",
"anonymousId": "anon_abc",
"events": \[
{
"eventName": "game_impression",
"occurredAt": "2026-05-28T10:00:00.000Z",
"gameId": "game_01HZAA1M0KQ8",
"properties": {
"position": 1,
"feedRequestId": "feed_req_123"
}
},
{
"eventName": "game_play_30s",
"occurredAt": "2026-05-28T10:00:32.000Z",
"gameId": "game_01HZAA1M0KQ8",
"properties": {
"fpsAvg": 52,
"loadTimeMs": 1800
}
}
\]
}
-
Third-party integrations
-
LLM Provider
- 用途:Prompt理解、模板分类、参数生成、失败解释。
- 协议:HTTPS JSON API。
- 要求:设置超时30秒、最大重试2次、供应商错误降级到默认模板建议。
-
图片生成或素材服务
- MVP可选,建议优先使用内置素材库与风格包,减少生成不确定性。
- 若接入图片生成,需进行内容安全检测和资源压缩。
-
内容安全服务
- 用途:文本、图片、用户资料、封面和Prompt检测。
- 协议:HTTPS API。
- 输出:pass、review、reject三类结果。
-
对象存储和CDN
- 用途:上传素材、生成资源、游戏包、封面和Manifest。
- 要求:私有源站,CDN公开只读;上传使用服务端签名URL。
-
数据分析工具
- MVP内部事件表即可,后续可对接GrowingIO、神策、Mixpanel或自建ClickHouse。
-
-
Internal modules
- AuthModule:登录、Token、角色、匿名用户升级。
- UserModule:用户资料、创作者主页。
- AssetModule:上传、扫描、压缩、对象存储签名。
- GenerationModule:任务创建、状态机、Prompt解析、GameConfig生成。
- GameModule:草稿、版本、发布、详情、Manifest管理。
- ReviewModule:审核队列、审核记录、下架、精选。
- FeedModule:候选集、排序、分页、曝光保底。
- InteractionModule:点赞、收藏、分享、举报。
- AnalyticsModule:事件接收、聚合、看板。
- AdminModule:后台权限、操作审计、系统配置。
User Interface
-
创作工作台
- 主区域:Prompt输入框、模板卡片、风格标签、上传素材入口。
- 任务页:生成状态、当前步骤、预计等待时间、失败原因和重试入口。
- 预览页:左侧游戏预览容器,右侧基础信息编辑面板。
- 发布页:发布前检查清单、审核状态说明、分享链接。
-
玩家游戏流
- 移动优先,全屏或近全屏纵向滑动。
- 每个游戏项包含封面、标题、作者、玩法提示、开始按钮、点赞、收藏、分享、举报。
- 游戏资源预加载下一项,当前项加载失败时显示错误提示并自动允许跳过。
- 低端设备启用低画质模式,限制帧率到30fps。
-
创作者后台
- 我的游戏列表:封面、标题、状态、曝光、试玩、互动、最后更新时间。
- 数据详情:近7天趋势、曝光到试玩漏斗、平均游玩时长、加载失败率、举报率。
- 操作:编辑、更新、下架、复制分享链接。
-
运营后台
- 审核队列:状态筛选、风险等级、发布时间、创作者、标签。
- 审核详情:游戏试玩、Prompt、生成配置、素材列表、安全检测结果、历史记录。
- 操作:通过、拒绝、下架、备注、加入精选池、限制曝光。
-
交互模式
- 关键流程必须有明确状态:加载中、成功、失败、禁用、重试。
- 生成任务超过120秒提示后台等待,不阻断用户离开页面。
- 所有破坏性操作使用二次确认,例如下架、删除草稿、拒绝审核。
-
可访问性与响应式设计
- 移动端优先适配360px至430px宽度。
- 桌面端优先优化创作工作台和运营后台。
- 文本对比度符合WCAG AA基础要求。
- 核心按钮支持键盘访问和可读ARIA标签。
- 错误提示不只依赖颜色表达,应同时使用文本和图标。
Data Model
How data is structured, stored, and accessed.
Entities
User
- id: uuid (primary key)
- phone: varchar(32) (nullable, unique)
- email: varchar(255) (nullable, unique)
- password_hash: varchar(255) (nullable)
- nickname: varchar(64) (not null)
- avatar_url: text (nullable)
- role: enum(player, creator, operator, admin) (not null, default player)
- status: enum(active, suspended, deleted) (not null, default active)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
CreatorProfile
- id: uuid (primary key)
- user_id: uuid (unique, foreign key User.id)
- slug: varchar(64) (unique, not null)
- bio: varchar(500) (nullable)
- total_games: integer (not null, default 0)
- total_plays: bigint (not null, default 0)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
Asset
- id: uuid (primary key)
- owner_id: uuid (foreign key User.id)
- type: enum(image, audio, json, game_bundle, manifest) (not null)
- source: enum(uploaded, generated, system) (not null)
- storage_key: text (not null)
- public_url: text (nullable)
- mime_type: varchar(128) (not null)
- size_bytes: integer (not null)
- width: integer (nullable)
- height: integer (nullable)
- hash_sha256: char(64) (not null)
- moderation_status: enum(pending, passed, review, rejected) (not null, default pending)
- created_at: timestamptz (not null)
PromptRecord
- id: uuid (primary key)
- user_id: uuid (foreign key User.id)
- raw_prompt: text (not null)
- normalized_prompt: text (nullable)
- template_hint: varchar(64) (nullable)
- style_tags: text\[\] (not null, default empty)
- moderation_status: enum(pending, passed, review, rejected) (not null)
- moderation_reason: text (nullable)
- created_at: timestamptz (not null)
GenerationTask
- id: uuid (primary key)
- user_id: uuid (foreign key User.id)
- prompt_record_id: uuid (foreign key PromptRecord.id)
- status: enum(queued, running, succeeded, failed, canceled, timed_out) (not null)
- progress: integer (0 to 100)
- current_step: varchar(64) (nullable)
- template_id: varchar(64) (nullable)
- llm_request_id: varchar(128) (nullable)
- error_code: varchar(64) (nullable)
- error_message: text (nullable)
- started_at: timestamptz (nullable)
- completed_at: timestamptz (nullable)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
Game
- id: uuid (primary key)
- creator_id: uuid (foreign key User.id)
- title: varchar(80) (not null)
- description: varchar(500) (not null)
- cover_asset_id: uuid (foreign key Asset.id, nullable)
- status: enum(draft, pending_review, published, rejected, unpublished, deleted) (not null)
- visibility: enum(private, public, limited) (not null, default private)
- tags: text\[\] (not null, default empty)
- age_rating: enum(all, teen, mature) (not null, default all)
- current_version_id: uuid (nullable)
- published_at: timestamptz (nullable)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
GameVersion
- id: uuid (primary key)
- game_id: uuid (foreign key Game.id)
- version_number: integer (not null)
- generation_task_id: uuid (foreign key GenerationTask.id, nullable)
- config_json: jsonb (not null)
- manifest_asset_id: uuid (foreign key Asset.id)
- bundle_asset_id: uuid (foreign key Asset.id, nullable)
- runtime_version: varchar(32) (not null)
- status: enum(draft, active, archived, failed) (not null)
- created_at: timestamptz (not null)
ReviewRecord
- id: uuid (primary key)
- game_id: uuid (foreign key Game.id)
- version_id: uuid (foreign key GameVersion.id)
- status: enum(pending, approved, rejected, escalated) (not null)
- risk_level: enum(low, medium, high) (not null, default low)
- reviewer_id: uuid (foreign key User.id, nullable)
- reason_code: varchar(64) (nullable)
- comment: text (nullable)
- created_at: timestamptz (not null)
- decided_at: timestamptz (nullable)
Interaction
- id: uuid (primary key)
- user_id: uuid (foreign key User.id, nullable)
- anonymous_id: varchar(128) (nullable)
- game_id: uuid (foreign key Game.id)
- type: enum(like, favorite, share, report) (not null)
- status: enum(active, canceled) (not null, default active)
- reason: varchar(128) (nullable, for report)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
EventLog
- id: uuid (primary key)
- event_name: varchar(64) (not null)
- user_id: uuid (nullable)
- anonymous_id: varchar(128) (nullable)
- session_id: varchar(128) (not null)
- game_id: uuid (nullable)
- properties: jsonb (not null)
- occurred_at: timestamptz (not null)
- received_at: timestamptz (not null)
GameDailyStats
- id: uuid (primary key)
- game_id: uuid (foreign key Game.id)
- stat_date: date (not null)
- impressions: bigint (not null, default 0)
- load_success: bigint (not null, default 0)
- load_failed: bigint (not null, default 0)
- play_starts: bigint (not null, default 0)
- play_30s: bigint (not null, default 0)
- completes: bigint (not null, default 0)
- likes: bigint (not null, default 0)
- favorites: bigint (not null, default 0)
- shares: bigint (not null, default 0)
- reports: bigint (not null, default 0)
- avg_play_duration_ms: integer (nullable)
- created_at: timestamptz (not null)
- updated_at: timestamptz (not null)
FeaturedGame
- id: uuid (primary key)
- game_id: uuid (foreign key Game.id)
- operator_id: uuid (foreign key User.id)
- priority: integer (not null, default 0)
- start_at: timestamptz (not null)
- end_at: timestamptz (nullable)
- created_at: timestamptz (not null)
AuditLog
- id: uuid (primary key)
- actor_id: uuid (foreign key User.id)
- action: varchar(128) (not null)
- target_type: varchar(64) (not null)
- target_id: uuid (not null)
- metadata: jsonb (not null)
- ip_address: inet (nullable)
- user_agent: text (nullable)
- created_at: timestamptz (not null)
Relationships
-
User → CreatorProfile:one-to-one;User删除时CreatorProfile软删除或保留匿名化记录。
-
User → Game:one-to-many;creator_id限制只能访问和修改自己的游戏。
-
User → Asset:one-to-many;上传素材归属用户,系统素材owner可为空或使用system user。
-
PromptRecord → GenerationTask:one-to-many;同一Prompt允许多次重试生成。
-
GenerationTask → GameVersion:one-to-one或one-to-many;一次成功生成可创建一个版本,重试可产生新版本。
-
Game → GameVersion:one-to-many;Game.current_version_id指向当前线上或草稿版本。
-
Game → ReviewRecord:one-to-many;每次发布提交生成一条审核记录。
-
Game → Interaction:one-to-many;同一用户对同一游戏的like和favorite应有唯一约束。
-
Game → GameDailyStats:one-to-many;按game_id和stat_date唯一。
-
Game → FeaturedGame:one-to-many;可配置多个时间段的精选计划。
-
ReviewRecord → User:many-to-one;reviewer_id为运营或管理员。
-
关键约束
- Game.status为published时必须存在current_version_id、cover_asset_id、title、description。
- GameVersion.config_json必须通过JSON Schema校验。
- Interaction唯一约束:user_id + game_id + type,适用于like和favorite;share和report允许多条但需要限频。
- EventLog按occurred_at月度分区,避免长期写入膨胀影响查询。
- 所有后台操作写入AuditLog。
Storage
-
数据库
-
PostgreSQL作为主库,承载用户、游戏、版本、审核、互动和聚合统计。
-
使用Prisma Migration管理Schema变更。
-
关键索引:
- Game(status, published_at desc)
- Game(creator_id, updated_at desc)
- ReviewRecord(status, created_at asc)
- Interaction(game_id, type)
- EventLog(occurred_at, event_name)
- GameDailyStats(game_id, stat_date)
-
-
缓存
- Redis缓存游戏详情、Manifest元数据、Feed候选集、用户会话和限频计数。
- Feed缓存TTL 60秒,热门游戏详情TTL 300秒。
- 生成任务状态可写PostgreSQL为准,Redis用于短期进度加速读取。
-
队列
- BullMQ队列:generation_queue、moderation_queue、asset_processing_queue、event_aggregation_queue、notification_queue。
- 每类任务配置重试次数、退避策略和死信队列。
-
文件/blob存储
- 原始上传素材:private bucket,需签名访问。
- 处理后封面和公开素材:public-read via CDN或私有源站加CDN回源。
- 游戏Manifest和bundle:版本化路径,例如/games/{gameId}/versions/{versionId}/manifest.json。
- 所有资源文件保留sha256 hash,用于去重、缓存和完整性校验。
Data Flow
-
创作生成流程
- 用户登录并进入创作工作台。
- 前端提交Prompt、模板提示、风格标签和素材ID。
- API Server创建PromptRecord和GenerationTask,写入generation_queue。
- Moderation Worker先检测Prompt和上传素材;若reject则任务失败并返回明确原因。
- Generation Worker调用LLM解析Prompt,选择模板并生成GameConfig。
- Worker使用JSON Schema和业务规则校验GameConfig。
- Worker生成或绑定素材,创建GameManifest并上传对象存储。
- Worker创建Game草稿和GameVersion,更新任务状态为succeeded。
- 前端轮询任务状态并跳转预览页。
-
发布审核流程
- 创作者编辑标题、简介、封面、标签和操作说明。
- 点击发布后,API执行发布前检查。
- 系统创建ReviewRecord并将Game置为pending_review。
- 低风险内容可自动通过或进入运营队列,具体由配置控制。
- 运营通过后Game置为published和public,写入AuditLog。
- Feed候选集下次刷新时包含该游戏,并为新作分配保底曝光。
-
玩家游戏流流程
- 玩家打开首页,前端请求/api/v1/feed。
- FeedModule从精选、最新、质量分候选池取数据并排序。
- 前端展示第一款游戏并预加载下一款Manifest和关键资源。
- 玩家开始试玩,Game SDK上报load、start、30s、complete和error事件。
- 前端批量调用/events/batch上报埋点。
- Event Worker聚合更新GameDailyStats和质量分。
- 后续Feed排序降低高错误、高举报游戏的曝光。
-
运营审核流程
- 运营登录后台,调用/admin/reviews获取待审核列表。
- 运营查看游戏详情、Prompt、安全检测结果和试玩预览。
- 运营提交通过、拒绝、下架或精选操作。
- API更新Game、ReviewRecord、FeaturedGame并写AuditLog。
Testing Plan
How the product will be validated at every level.
Testing Strategy
-
Unit tests
- 覆盖范围:Prompt解析适配器、GameConfig校验、状态机转换、Feed评分、权限Guard、事件聚合逻辑。
- 框架:Vitest或Jest。
- 覆盖目标:核心业务模块行覆盖率不低于80%,状态机和权限模块不低于90%。
-
Integration tests
- 覆盖范围:REST API、PostgreSQL、Redis Queue、对象存储Mock、内容安全Mock、LLM Mock。
- 重点验证:生成任务创建到成功、发布审核、游戏流返回、互动写入、事件聚合。
- 使用Testcontainers启动PostgreSQL和Redis,避免只依赖内存Mock。
-
E2E tests
- 框架:Playwright。
- 覆盖关键用户流:创作者生成游戏、预览发布、运营审核、玩家游戏流试玩互动、创作者查看数据。
- 移动端视口必须覆盖iPhone和Android常见宽度。
-
Performance tests
-
工具:k6。
-
目标:
- /feed P95低于300ms,不含CDN资源加载。
- /events/batch P95低于200ms。
- /generation/tasks创建任务P95低于500ms。
- 500并发玩家浏览Feed时错误率低于1%。
- 每分钟5,000条事件写入时队列无持续积压。
-
-
Game runtime tests
- 使用自动化脚本加载每个模板生成的Manifest。
- 验证资源存在、启动成功、SDK事件发出、低端设备模拟下帧率不低于30fps。
- 对每个模板维护golden config样例。
Testing Tools
-
Frontend
- Vitest:组件逻辑和工具函数。
- React Testing Library:UI状态和交互。
- Playwright:跨浏览器和移动视口E2E。
- Lighthouse CI:性能、可访问性和最佳实践检查。
-
Backend
- Jest或Vitest:服务、控制器和状态机单测。
- Supertest:API集成测试。
- Testcontainers:PostgreSQL和Redis依赖环境。
- Prisma migrate diff:Schema变更验证。
-
Game runtime
- Playwright:加载游戏容器并监听SDK事件。
- 自定义Manifest Validator:校验Manifest资源、hash和字段完整性。
-
Performance and security
- k6:API压测。
- OWASP ZAP Baseline Scan:基础Web安全扫描。
- npm audit、pnpm audit、Snyk或GitHub Dependabot:依赖漏洞扫描。
-
CI integration
- Pull Request阶段:lint、type check、unit tests、API integration tests、build。
- Merge to main阶段:完整测试、Docker镜像构建、安全扫描、部署到staging。
- Release阶段:staging E2E、性能冒烟、手动批准生产部署。
-
Code coverage
- 全仓库最低70%。
- 核心后端业务模块最低80%。
- 权限、审核和发布状态机最低90%。
- 覆盖率不达标阻断合并。
Key Test Cases
-
创作链路Happy Path
- 创作者登录。
- 输入合法Prompt并选择模板。
- 创建生成任务成功。
- Worker生成GameConfig和Manifest。
- 前端预览成功加载游戏。
- 创作者填写标题、封面、标签并保存。
-
发布与审核
- 发布前缺少标题时返回明确错误。
- 内容安全reject时不得进入公开Feed。
- pending_review游戏只有作者和运营可访问。
- 运营通过后游戏出现在Feed候选集中。
- 运营拒绝后创作者看到原因且可修改重提。
-
玩家游戏流
- 未登录用户可以浏览和试玩。
- 未登录用户点击点赞时触发登录引导,并在登录后恢复操作上下文。
- 游戏加载失败时记录game_load_failed并允许跳过。
- 上下滑动切换不会重复曝光同一游戏,除非列表耗尽。
- 下一款游戏资源成功预加载。
-
互动与埋点
- 同一用户重复点赞不会重复计数。
- 收藏取消后状态更新为canceled。
- 举报行为触发风险信号并对同一匿名用户限频。
- 批量事件中部分无效事件不影响有效事件写入。
- Event Worker聚合后数据看板数值正确。
-
权限与安全敏感操作
- 普通用户不能访问/admin接口。
- 创作者不能编辑他人游戏。
- 运营操作必须写入AuditLog。
- 已删除或下架游戏不能在公开Feed返回。
- 上传非图片或超大文件会被拒绝。
-
性能边界
- 单个游戏Manifest资源超过大小限制时生成失败并返回可理解原因。
- 高并发Feed请求不造成数据库慢查询。
- Redis不可用时Feed可降级为数据库读取并告警。
- LLM超时后任务进入failed或timed_out,允许用户重试。
Reporting
-
CI报告
- GitHub Actions或GitLab CI展示每次PR的测试、覆盖率、构建和安全扫描结果。
- 失败测试必须阻断合并。
-
质量看板
- Grafana展示API错误率、P95延迟、队列长度、生成成功率、游戏加载失败率。
- Sentry展示前端错误、游戏运行错误和后端异常。
- 每日自动生成MVP质量报告:生成任务数、成功率、平均生成时长、审核积压、Feed错误率。
-
缺陷管理
- P0:核心链路不可用、权限绕过、数据丢失、安全事故。
- P1:生成成功率显著下降、游戏流加载异常、审核流程阻塞。
- P2:单页面体验问题、非关键统计延迟、文案错误。
Deployment Plan
How the product moves from code to production.
Environment Setup
-
Development
- 本地运行Docker Compose:PostgreSQL、Redis、MinIO、本地邮件或通知Mock。
- 前端Next.js热更新运行在localhost:3000。
- 后端NestJS运行在localhost:4000。
- Worker独立进程运行generation、moderation和event aggregation。
- 使用seed脚本创建管理员、运营、示例创作者、示例游戏和模板数据。
- LLM和内容安全默认使用Mock Provider,可通过环境变量切换真实Provider。
-
Staging
- 与生产同构但缩小规格。
- 使用独立PostgreSQL、Redis、OSS bucket和CDN域名。
- 接入真实内容安全服务,LLM可使用较低成本模型。
- 仅允许白名单用户访问创作和后台。
- 每次main合并自动部署。
-
Production
-
云基础设施建议:
- API Server运行在Kubernetes、ECS、Cloud Run或Render/Fly.io等容器平台。
- Worker按队列类型独立部署,可横向扩容。
- PostgreSQL使用云托管数据库,开启自动备份和只读副本预留。
- Redis使用托管版,开启持久化和监控。
- 静态前端部署到Vercel、Netlify或对象存储加CDN。
-
生产访问必须使用HTTPS。
-
所有Secrets从云Secret Manager或Vault读取,不写入代码仓库。
-
CI/CD Pipeline
-
Build steps
- 安装依赖:pnpm install --frozen-lockfile。
- 静态检查:eslint、prettier check。
- 类型检查:tsc --noEmit。
- 单元测试:vitest/jest with coverage。
- 集成测试:Testcontainers PostgreSQL和Redis。
- 前端构建:next build。
- 后端构建:nest build。
- Docker镜像构建并打tag。
- 依赖漏洞扫描和镜像扫描。
-
Deployment trigger
- Pull Request:创建Preview Deployment,仅连接staging级别Mock服务。
- Merge to main:自动部署Staging。
- Production:手动批准发布,建议每周固定窗口或MVP阶段按需发布。
-
Preview deployments
- 每个PR生成前端预览URL。
- 后端可共享staging API或部署临时环境。
- Preview环境禁止使用真实用户数据和真实支付/广告相关配置。
Deploy Process
- 准备发布版本
- 确认main分支CI全绿。
- 确认数据库Migration已在staging成功执行。
- 确认Feature Flag默认值符合发布策略。
- Verification checkpoint:staging smoke tests通过,错误率无异常。
- 执行数据库迁移
- 在生产数据库执行向后兼容Migration。
- 禁止直接删除字段或重命名字段;采用expand-migrate-contract策略。
- Verification checkpoint:迁移执行成功,关键表读写正常。
- 部署后端API
- 使用滚动发布或蓝绿部署。
- 保持旧版本至少可服务5至10分钟,确保无中断。
- Verification checkpoint:/health、/ready、登录、Feed接口正常。
- 部署Worker
- 先暂停或降低新任务消费。
- 部署Worker新版本。
- 恢复队列消费并观察失败率。
- Verification checkpoint:generation_queue和event_aggregation_queue无异常积压。
- 部署前端
- 发布Next.js前端或静态资源。
- 刷新CDN缓存中需要更新的HTML和Manifest加载脚本。
- Verification checkpoint:创作工作台、游戏流、后台入口可访问。
- 灰度开启功能
- 使用Feature Flag先对内部用户开放。
- 观察30至60分钟后扩大到种子用户。
- Verification checkpoint:生成成功率、Feed错误率、Sentry错误无异常增长。
Rollback Strategy
-
应用回滚
- 保留最近3个稳定Docker镜像。
- API和Worker可通过部署平台一键回滚到上一版本。
- 前端可通过Vercel/Netlify回滚或CDN切回上一构建。
-
数据库回滚
- 优先使用向后兼容Migration避免必须回滚数据库。
- 对高风险Migration预先准备rollback SQL。
- 删除数据类操作必须先备份,MVP阶段原则上不做破坏性Migration。
-
Feature flags
- generation_v2_enabled:控制新生成链路。
- feed_ranking_v2_enabled:控制新推荐评分。
- auto_review_enabled:控制自动审核通过。
- external_asset_generation_enabled:控制外部图片生成服务。
- 任何P0异常优先关闭相关Flag,而不是全站回滚。
-
队列回滚
- Worker新版本异常时暂停队列消费。
- 将失败任务标记为retryable或保持queued,待旧版本恢复后继续消费。
- 对不兼容任务payload使用version字段区分处理逻辑。
Post-Deploy Verification
-
Smoke tests
- 用户登录成功。
- 创建生成任务成功,Mock或真实低成本生成可完成。
- 预览游戏可加载并触发game_load_success。
- 游戏可提交审核。
- 运营可通过审核。
- 已发布游戏可出现在Feed。
- 点赞、收藏和埋点上报成功。
-
Monitoring dashboards
- API Latency:P50、P95、P99。
- API Error Rate:4xx、5xx分布。
- Queue Health:等待数、处理中、失败数、平均处理时长。
- Generation Health:成功率、失败原因、平均生成时长。
- Game Runtime:加载成功率、运行错误率、平均FPS、资源加载时长。
- Database:CPU、连接数、慢查询、锁等待。
- CDN:命中率、回源错误、流量峰值。
-
Alert thresholds
- API 5xx错误率5分钟内超过2%触发P1告警。
- /feed P95超过800ms持续10分钟触发P1告警。
- 生成成功率15分钟内低于70%触发P1告警。
- generation_queue等待任务超过500或最老任务等待超过10分钟触发P1告警。
- 游戏加载失败率超过8%持续15分钟触发P1告警。
- 数据库连接使用率超过85%持续10分钟触发P1告警。
- 权限相关异常或后台接口未授权访问激增触发P0安全告警。
Security & Performance
Non-functional requirements and how they are addressed.
Security
-
Authentication
- 使用JWT Access Token和Refresh Token。
- Access Token有效期15分钟,Refresh Token有效期7至30天。
- Refresh Token存储hash,支持注销和设备级撤销。
- 游客使用anonymous_id,只允许浏览和试玩,不允许发布、收藏和后台操作。
-
Authorization
- 使用RBAC:player、creator、operator、admin。
- 所有修改游戏、审核、精选、下架和查看后台接口必须校验角色和资源归属。
- 后台接口单独命名空间/admin,并增加IP风险监控和操作审计。
-
Input validation and sanitization
- API使用Zod或class-validator校验请求。
- Prompt长度限制,例如10至1,000字符。
- 标题限制80字符,简介限制500字符,标签数量限制10个。
- 上传文件限制MIME、扩展名、大小和尺寸。
- 所有用户可见文本输出做HTML escaping,禁止直接渲染未清洗HTML。
-
Game sandboxing
- 游戏运行在受控iframe或隔离容器中。
- 禁止生成游戏访问任意网络、Cookie、localStorage和父页面DOM。
- Game SDK只暴露有限能力:事件上报、结束游戏、读取配置。
- 设置Content Security Policy限制脚本源、资源源和frame权限。
-
Secrets management
- 本地开发使用.env.local,不提交仓库。
- Staging和Production使用Secret Manager或Vault。
- LLM、内容安全、OSS、数据库和Redis凭证定期轮换。
- 日志中禁止输出Token、手机号、邮箱、Prompt敏感检测明文结果和第三方API Key。
-
Dependency vulnerability scanning
- Pull Request阶段运行pnpm audit或Snyk。
- Docker镜像使用Trivy或云厂商镜像扫描。
- Dependabot自动提交安全升级PR。
-
OWASP Top 10 considerations
- Broken Access Control:RBAC、资源归属校验、后台审计。
- Cryptographic Failures:HTTPS、数据库备份加密、敏感字段加密或脱敏。
- Injection:Prisma参数化查询,禁止拼接SQL;Prompt不直接作为系统指令执行。
- Insecure Design:状态机限制非法发布和审核状态转换。
- Security Misconfiguration:CSP、CORS白名单、生产关闭debug、对象存储私有源站。
- Vulnerable Components:依赖扫描和锁文件审计。
- Identification and Authentication Failures:Refresh Token轮换、登录限频、密码hash使用Argon2或bcrypt。
- Software and Data Integrity Failures:游戏Manifest hash校验,CI签名镜像可选。
- Security Logging and Monitoring Failures:后台操作、登录失败、安全拒绝全部记录。
- SSRF:后端不允许用户提交任意URL抓取资源;如后续支持,必须使用URL allowlist和内网IP阻断。
-
Content safety and compliance
- Prompt、标题、简介、封面和上传素材均经过内容安全检测。
- risk_level为high时自动拒绝,medium进入人工审核,low可进入普通审核或自动通过。
- 举报达到阈值时自动限制曝光并进入运营复核。
- 针对未成年人保护、版权素材和暴力色情等内容建立可配置策略。
Performance
-
Targets
- 游戏流API响应:P95低于300ms,P99低于800ms。
- 游戏详情API响应:P95低于200ms。
- 埋点批量上报API响应:P95低于200ms。
- 生成任务创建API响应:P95低于500ms。
- 生成任务完成时长:P75低于120秒,P95低于240秒。
- 游戏流首屏可交互时间:P75低于3秒,P95低于6秒。
- 游戏运行帧率:中端移动设备平均不低于45fps,低端设备低画质不低于30fps。
- 平台吞吐:MVP支持500并发浏览用户、每分钟5,000条埋点事件、每日1,000次生成任务。
-
Optimization
-
前端
- Next.js路由级代码分割。
- 游戏流只保留当前、前一、后一三个游戏容器。
- 图片使用WebP/AVIF,封面多尺寸裁剪。
- 下一款游戏Manifest和关键资源预加载。
- 埋点异步批量发送,使用sendBeacon兜底。
-
后端
- 高频读接口使用Redis缓存。
- Feed候选集预计算或短TTL缓存。
- 事件写入走批量insert,聚合异步执行。
- 数据库连接池按实例规格配置,避免连接耗尽。
-
资源
- 游戏bundle hash命名,CDN长期缓存。
- 限制单游戏总资源大小和首屏关键资源大小。
- 音频延迟加载,非关键图片懒加载。
-
Worker
- 生成Worker按队列长度自动扩容。
- LLM调用设置超时、重试和熔断。
- 资产处理使用并发限制,避免CPU尖峰。
-
-
Monitoring
- APM:OpenTelemetry trace跨API、Worker和数据库。
- Error tracking:Sentry捕获前端、Game Runtime和后端异常。
- Custom metrics:生成成功率、审核积压、Feed曝光、游戏加载失败率、互动率。
-
Scaling
-
MVP阶段:API Server 2个实例,Worker按队列1至3个实例,PostgreSQL单主实例,Redis托管实例。
-
增长阶段:
- API Server水平扩容。
- Generation Worker按任务量独立扩容。
- Event Worker和Analytics迁移到ClickHouse或数据仓库。
- Feed Service从API Server拆分为独立服务。
- PostgreSQL增加只读副本,读多写少接口走读副本。
-
Auto-scaling配置
- API:CPU超过65%或RPS超过阈值扩容。
- Worker:队列等待任务数超过100或最老任务等待超过2分钟扩容。
- Event Worker:事件队列积压超过10,000条扩容。
-
Observability
-
Logging strategy
- 使用结构化JSON日志。
- 所有日志包含request_id、user_id可选、anonymous_id可选、module、operation、duration_ms、status。
- 生成任务日志包含task_id、template_id、provider、error_code,但不直接记录敏感Prompt全文。
- 审核和后台操作写AuditLog并长期保存。
- 日志保留:应用日志30天,审计日志至少180天,安全日志至少180天。
-
Metrics
-
Product metrics
- creator_activation_rate。
- generation_success_rate。
- first_publish_conversion_rate。
- feed_session_games_played。
- game_interaction_rate。
- player_d7_retention。
-
System metrics
- API RPS、latency、error rate。
- Queue depth、processing time、failure count。
- Database CPU、connections、slow queries、locks。
- Redis memory、hit rate、evictions。
- CDN hit rate、origin error rate。
-
Game metrics
- game_load_time_ms。
- game_load_failed_rate。
- runtime_error_rate。
- fps_avg。
- asset_size_bytes。
-
-
Alerting
- 告警渠道:飞书、Slack、邮件或短信,按严重级别区分。
- P0响应:核心链路不可用、安全事故、数据丢失,15分钟内响应。
- P1响应:生成失败率异常、Feed延迟异常、队列严重积压,工作时间30分钟内响应。
- P2响应:非核心页面错误、低频统计延迟,下一工作日处理。
- 每个告警必须包含Runbook链接:问题现象、排查仪表盘、常见原因、回滚步骤和负责人。