1172 lines
45 KiB
Markdown
1172 lines
45 KiB
Markdown
# 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示例
|
||
|
||
```json
|
||
{
|
||
"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|
|
||
|
||
- 创建生成任务请求示例
|
||
|
||
```json
|
||
{
|
||
"prompt": "做一个像素风太空躲避游戏,玩家控制飞船躲避陨石,收集能量块,坚持60秒获胜。",
|
||
"templateHint": "avoidance",
|
||
"styleTags": \["pixel", "space"\],
|
||
"uploadedAssetIds": \["asset_01HXYZ"\]
|
||
}
|
||
|
||
```
|
||
|
||
- 创建生成任务响应示例
|
||
|
||
```json
|
||
{
|
||
"taskId": "gt_01HZA9Z9H4Q7",
|
||
"status": "queued",
|
||
"estimatedSeconds": 90,
|
||
"pollingIntervalMs": 2000
|
||
}
|
||
|
||
```
|
||
|
||
- 查询生成任务响应示例
|
||
|
||
```json
|
||
{
|
||
"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
|
||
}
|
||
|
||
```
|
||
|
||
- 获取游戏流请求示例
|
||
|
||
```http
|
||
GET /api/v1/feed?cursor=eyJzY29yZSI6MTIzfQ&limit=10&device=mobile
|
||
Authorization: Bearer optional
|
||
|
||
```
|
||
|
||
- 获取游戏流响应示例
|
||
|
||
```json
|
||
{
|
||
"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"
|
||
}
|
||
|
||
```
|
||
|
||
- 批量埋点请求示例
|
||
|
||
```json
|
||
{
|
||
"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
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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)
|
||
|
||
```
|
||
|
||
```text
|
||
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
|
||
|
||
- 创作生成流程
|
||
|
||
1. 用户登录并进入创作工作台。
|
||
2. 前端提交Prompt、模板提示、风格标签和素材ID。
|
||
3. API Server创建PromptRecord和GenerationTask,写入generation_queue。
|
||
4. Moderation Worker先检测Prompt和上传素材;若reject则任务失败并返回明确原因。
|
||
5. Generation Worker调用LLM解析Prompt,选择模板并生成GameConfig。
|
||
6. Worker使用JSON Schema和业务规则校验GameConfig。
|
||
7. Worker生成或绑定素材,创建GameManifest并上传对象存储。
|
||
8. Worker创建Game草稿和GameVersion,更新任务状态为succeeded。
|
||
9. 前端轮询任务状态并跳转预览页。
|
||
- 发布审核流程
|
||
|
||
1. 创作者编辑标题、简介、封面、标签和操作说明。
|
||
2. 点击发布后,API执行发布前检查。
|
||
3. 系统创建ReviewRecord并将Game置为pending_review。
|
||
4. 低风险内容可自动通过或进入运营队列,具体由配置控制。
|
||
5. 运营通过后Game置为published和public,写入AuditLog。
|
||
6. Feed候选集下次刷新时包含该游戏,并为新作分配保底曝光。
|
||
- 玩家游戏流流程
|
||
|
||
1. 玩家打开首页,前端请求/api/v1/feed。
|
||
2. FeedModule从精选、最新、质量分候选池取数据并排序。
|
||
3. 前端展示第一款游戏并预加载下一款Manifest和关键资源。
|
||
4. 玩家开始试玩,Game SDK上报load、start、30s、complete和error事件。
|
||
5. 前端批量调用/events/batch上报埋点。
|
||
6. Event Worker聚合更新GameDailyStats和质量分。
|
||
7. 后续Feed排序降低高错误、高举报游戏的曝光。
|
||
- 运营审核流程
|
||
|
||
1. 运营登录后台,调用/admin/reviews获取待审核列表。
|
||
2. 运营查看游戏详情、Prompt、安全检测结果和试玩预览。
|
||
3. 运营提交通过、拒绝、下架或精选操作。
|
||
4. 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
|
||
|
||
1. 安装依赖:pnpm install --frozen-lockfile。
|
||
2. 静态检查:eslint、prettier check。
|
||
3. 类型检查:tsc --noEmit。
|
||
4. 单元测试:vitest/jest with coverage。
|
||
5. 集成测试:Testcontainers PostgreSQL和Redis。
|
||
6. 前端构建:next build。
|
||
7. 后端构建:nest build。
|
||
8. Docker镜像构建并打tag。
|
||
9. 依赖漏洞扫描和镜像扫描。
|
||
- Deployment trigger
|
||
|
||
- Pull Request:创建Preview Deployment,仅连接staging级别Mock服务。
|
||
- Merge to main:自动部署Staging。
|
||
- Production:手动批准发布,建议每周固定窗口或MVP阶段按需发布。
|
||
- Preview deployments
|
||
|
||
- 每个PR生成前端预览URL。
|
||
- 后端可共享staging API或部署临时环境。
|
||
- Preview环境禁止使用真实用户数据和真实支付/广告相关配置。
|
||
|
||
### Deploy Process
|
||
|
||
1. 准备发布版本
|
||
|
||
- 确认main分支CI全绿。
|
||
- 确认数据库Migration已在staging成功执行。
|
||
- 确认Feature Flag默认值符合发布策略。
|
||
- Verification checkpoint:staging smoke tests通过,错误率无异常。
|
||
|
||
2. 执行数据库迁移
|
||
|
||
- 在生产数据库执行向后兼容Migration。
|
||
- 禁止直接删除字段或重命名字段;采用expand-migrate-contract策略。
|
||
- Verification checkpoint:迁移执行成功,关键表读写正常。
|
||
|
||
3. 部署后端API
|
||
|
||
- 使用滚动发布或蓝绿部署。
|
||
- 保持旧版本至少可服务5至10分钟,确保无中断。
|
||
- Verification checkpoint:/health、/ready、登录、Feed接口正常。
|
||
|
||
4. 部署Worker
|
||
|
||
- 先暂停或降低新任务消费。
|
||
- 部署Worker新版本。
|
||
- 恢复队列消费并观察失败率。
|
||
- Verification checkpoint:generation_queue和event_aggregation_queue无异常积压。
|
||
|
||
5. 部署前端
|
||
|
||
- 发布Next.js前端或静态资源。
|
||
- 刷新CDN缓存中需要更新的HTML和Manifest加载脚本。
|
||
- Verification checkpoint:创作工作台、游戏流、后台入口可访问。
|
||
|
||
6. 灰度开启功能
|
||
|
||
- 使用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链接:问题现象、排查仪表盘、常见原因、回滚步骤和负责人。
|