# 后台管理服务设计 日期:`2026-04-23` ## 1. 目标 为当前 Rust `api-server` 增加一套同源后台管理服务,满足以下首版目标: 1. 支持管理员用户名密码登录。 2. 支持独立的管理员鉴权,不允许普通玩家 JWT 越权访问。 3. 支持在后台查看当前服务与数据库概览信息。 4. 支持在后台测试当前 `api-server` 已挂载接口。 5. 保持首版工程足够轻量,不新建额外独立服务进程,不引入第二套前端工程。 ## 2. 背景与约束 当前仓库已具备: 1. Rust `api-server` 主链。 2. 基于 JWT + refresh session 的普通用户登录体系。 3. `SpacetimeDB + spacetime-client` 的主数据面。 本次后台管理服务必须继续遵守: 1. 后端统一落在 `server-rs`,不回退到 `server-node`。 2. 不额外新起独立管理服务进程。 3. 首版以“一个受保护管理域 + 一个同源后台页面”为落地形态。 4. 数据库信息必须尽量读取真实数据库侧信息,不能只展示硬编码假数据。 ## 3. 首版范围 ### 3.1 包含 1. `GET /admin`:后台管理页面入口。 2. `POST /admin/api/login`:管理员用户名密码登录。 3. `GET /admin/api/me`:当前管理员会话信息。 4. `GET /admin/api/overview`:服务与数据库概览。 5. `POST /admin/api/debug/http`:受控 HTTP 接口调试。 6. 基于 Bearer JWT 的管理员鉴权中间件。 ### 3.2 不包含 1. 多角色管理员体系。 2. 管理员 refresh cookie / 多端会话管理。 3. 后台直接写库、删库、执行 reducer。 4. 任意 SQL 执行器。 5. 新建独立 React/Vite 管理端工程。 ## 4. 总体方案 ### 4.1 部署形态 后台管理服务直接挂载在现有 `server-rs/crates/api-server` 内,作为同一个 Axum 进程的一部分。 原因: 1. 当前 `api-server` 已具备配置、JWT、错误包裹、日志与同源路由能力。 2. 后台本质上是服务运维与调试面,不值得单独再起一个网关或 BFF。 3. 同源可以避免开发期额外 CORS 和 cookie 域问题。 ### 4.2 页面形态 后台管理页面采用 `api-server` 直接返回一份内嵌 HTML/CSS/JS 的管理页。 原因: 1. 首版目标是“可用的后台能力”,不是新建一套复杂前端基建。 2. 管理页面交互相对简单,直接内嵌更易随服务端一起部署。 3. 可以避免新增构建链和静态资源发布路径。 ### 4.3 数据库信息来源 数据库概览不走本地 CLI shell,也不依赖前端直接访问数据库。 首版采用两类信息源: 1. 服务端配置与连接信息:来自 `api-server` 当前 `AppConfig`。 2. SpacetimeDB 真正的数据库元信息与表行数:由 `api-server` 通过 SpacetimeDB 官方 HTTP API 读取。 读取口径: 1. `/v1/database/{database}`:读取数据库基础信息。 2. `/v1/database/{database}/schema`:读取 schema 信息。 3. `/v1/database/{database}/sql`:对受控表执行 `SELECT COUNT(*)` 统计。 说明: 1. 首版只做只读概览,不暴露任意 SQL 输入。 2. 表清单由后端显式维护,避免用户在后台拼接任意查询。 ## 5. 管理员鉴权设计 ### 5.1 管理员账号来源 首版不复用普通玩家账号仓储,不把管理员账号混进 `module-auth` 用户表。 管理员账号来自环境变量: 1. `GENARRATIVE_ADMIN_USERNAME` 2. `GENARRATIVE_ADMIN_PASSWORD` 原因: 1. 管理员是平台运维身份,不等于玩家账号。 2. 首版目标是尽快落地可靠后台,不引入额外管理员表迁移。 3. 环境变量方案最适合当前阶段的单后台入口。 ### 5.2 管理员 JWT 后台登录成功后签发独立管理员 Bearer JWT。 claims 设计: 1. 继续复用 `platform-auth::AccessTokenClaims`。 2. `roles` 固定包含 `admin`。 3. `sub` 使用稳定管理员主体,例如 `admin:`。 4. `sid` 使用后台会话 ID。 5. 不写 refresh cookie。 ### 5.3 权限校验 新增 `require_admin_auth` 中间件,校验规则如下: 1. Bearer token 必须可被当前 JWT 配置正确验签。 2. `roles` 中必须包含 `admin`。 3. `sub` 必须匹配当前管理员配置主体。 普通用户 token 即使同样由本服务签发,只要不带 `admin` 角色,也一律拒绝访问后台接口。 ## 6. 后台页面设计 首版页面包含三个主区域: 1. 登录卡片。 2. 数据库概览面板。 3. API 调试面板。 交互原则: 1. 页面简洁,不默认塞说明性长文案。 2. 移动端优先,窄屏下卡片改纵向堆叠。 3. API 调试结果在独立结果面板展示,不在按钮下方临时插一段文本。 ## 7. 数据库概览设计 `GET /admin/api/overview` 返回以下信息: 1. 当前服务监听信息。 2. 当前 `SpacetimeDB server/database` 配置。 3. `SpacetimeDB` 数据库基础信息。 4. 当前 schema 表清单。 5. 首批关键表的行数统计。 首批关键表固定覆盖: 1. `runtime_setting` 2. `runtime_snapshot` 3. `user_browse_history` 4. `profile_dashboard_state` 5. `profile_wallet_ledger` 6. `profile_played_world` 7. `profile_save_archive` 8. `story_session` 9. `story_event` 10. `battle_state` 11. `inventory_slot` 12. `quest_record` 13. `quest_log` 14. `treasure_record` 15. `npc_state` 16. `custom_world_profile` 17. `custom_world_gallery_entry` 18. `custom_world_agent_session` 19. `custom_world_agent_message` 20. `custom_world_agent_operation` 21. `custom_world_draft_card` 22. `big_fish_creation_session` 23. `big_fish_agent_message` 24. `big_fish_asset_slot` 25. `big_fish_runtime_run` 26. `puzzle_work_profile` 27. `puzzle_agent_session` 28. `puzzle_agent_message` 29. `puzzle_runtime_run` 30. `ai_task` 31. `ai_task_stage` 32. `ai_text_chunk` 33. `ai_result_reference` 34. `asset_object` 35. `asset_entity_binding` 返回中的计数失败项必须带错误信息,不能静默吞掉。 ## 8. API 调试设计 `POST /admin/api/debug/http` 提供一个受控 HTTP 调试代理。 请求参数: 1. `method` 2. `path` 3. `headers` 4. `body` 限制: 1. 只允许访问当前服务同源相对路径。 2. 调试回环地址由服务端按当前 `bind_host` 解析;若服务监听在 `0.0.0.0` 或 `::`,后台自动改走 loopback,避免把通配监听地址直接当成调试目标。 2. 禁止调 `/admin/api/login` 本身,避免自套娃。 3. 禁止覆盖 `host`、`content-length` 等危险头。 4. 请求超时固定收口。 5. 返回调试结果时回显状态码、响应头、响应文本预览。 该能力用于验证当前服务端接口,不等价于通用代理工具。 ## 9. 配置项 新增以下环境变量: 1. `GENARRATIVE_ADMIN_USERNAME` 2. `GENARRATIVE_ADMIN_PASSWORD` 3. `GENARRATIVE_ADMIN_TOKEN_TTL_SECONDS` 默认策略: 1. 若未配置用户名或密码,则后台登录接口返回 `503`,后台页面显示“后台未启用”。 2. 默认管理员 token TTL 为 `4` 小时。 ## 10. 测试要求 至少覆盖: 1. 管理员登录成功。 2. 管理员密码错误返回 `401`。 3. 普通用户 token 访问后台接口返回 `403`。 4. 未登录访问后台接口返回 `401`。 5. 后台概览接口在未启用管理员配置时返回 `503`。 6. API 调试接口能成功访问 `/healthz`。 7. API 调试接口拒绝绝对 URL 和后台自身登录接口。 ## 11. 路由清单 首版新增路由: 1. `GET /admin` 2. `POST /admin/api/login` 3. `GET /admin/api/me` 4. `GET /admin/api/overview` 5. `POST /admin/api/debug/http` ## 12. 完成定义 满足以下条件时,本任务视为完成: 1. `api-server` 内存在受保护后台管理域。 2. 管理员用户名密码可登录。 3. 普通用户 token 无法访问后台接口。 4. 后台能看到服务和数据库真实概览。 5. 后台能调试当前服务 HTTP 接口。 6. 路由索引与技术文档已同步更新。