Files

1006 lines
73 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MiragenFlow 一期开发规划
> 本文是产品、前台、后台和服务端网关的一期设计基线。实现按本文分阶段落地,未完成部分必须在验收记录中明确,不得用演示数据冒充完成。
>
> 参考产品:`https://holopix.cn/`。参考重点是它的功能理念和工作流组织方式,不复制其品牌、文案、素材或内部实现。
## 0. 一期目标与已知约束
### 0.1 一期目标
把 MiragenFlow 从“浏览器直连模型的本地画布工具”升级为一个具备完整商业化基础链路的 AI 游戏美术创作产品:
```text
注册/登录
-> 获取公开模型产品目录
-> 选择模型档位、分辨率和创作参数
-> 提交图片/文本/音频/图片工具任务
-> 服务端鉴权、校验、预扣余额
-> 按模型产品绑定的渠道分组顺序路由
-> 单渠道失败自动切换后续渠道
-> 返回任务进度和结果
-> 成功扣除实际消耗,失败释放预扣余额
-> 结果进入画布、资产库和历史记录
```
### 0.2 本文直接采用的设计原则
1. **前台用户只看到产品能力,不看到供应商内部信息。** 用户看到“基础模型 / 高级模型 / 旗舰模型”和后台配置的分辨率、数量、价格,不直接看到供应商 API Key、渠道地址或原始 provider model ID。
2. **模型产品和供应商渠道解耦。** 用户选择的是 `modelProduct`,后台把它绑定到一个有顺序的 `channelGroup`;组内可以放多个供应商账号和多个内部模型 ID。
3. **组内按顺序故障切换。** 第一个渠道超时、限流、网关错误或被管理员禁用时,自动尝试下一个渠道;不会因为单个供应商故障直接中断用户任务。
4. **不做静默降档。** 一个旗舰模型组全部不可用时,任务明确失败并建议用户切换到其他旗舰模型;除非管理员显式配置,不自动把旗舰请求降级为高级或基础模型。
5. **余额制计费。** 充值增加余额,任务按公开价格和当前余额单位扣减;所有扣款、预扣、释放、退款均进入不可变账本。
6. **现有 OpenAI 图片协议优先迁移。** 无限画布项目已有的图片生成、图片编辑、响应解析和错误归一化逻辑迁移到服务端网关/供应商适配层,前台不再保存外部 API Key 并直连供应商。
7. **WebDAV 继续保留。** 它用于用户保存画布、资产和生成文件;一期不把 WebDAV 误写成平台自带云盘,也不强制把全部大图永久存放在平台服务器。
8. **视频和动画先不开发。** Holopix 的视频、首尾帧、图生视频、文生视频和动画能力作为参考差距记录,但不进入当前一期开发清单。音频生成保留。
9. **V1 认证增强可配置。** 不接第三方登录;用户邮箱/手机号验证、图形验证码或等价人机校验、登录风控和两步验证都保留为可配置能力,普通用户默认关闭,后台开启后才生效。管理员保持独立认证域,邮箱+密码为默认登录链路;管理员 MFA、管理员人机验证码等增强策略也由后台开关控制,默认关闭,开启/关闭均记录审计。
10. **V1 统一使用可配置余额单位。** 用户界面显示“金币”或后台配置的文字/图标单位,不出现“积分”概念。充值货币通过后台发布的换算比例转成余额单位,账本使用最小整数单位记录。
11. **V1 强制异步任务和 WebSocket。** 生图、音频、反推、拆分、多角度等耗时操作统一进入队列;WebSocket 是长任务进度的主通道,轮询只作为断线或兼容降级。
12. **V1 存储为浏览器本地 + WebDAV。** 平台对象存储只实现接口和适配器边界,不作为一期默认持久化目标;服务端临时 staging 文件必须隔离于静态目录并按 TTL 清理。
13. **真正的图生 3D/文生 3D 延后。** 在没有确认可稳定生成、导出和预览的模型前,V1 不开放 3D 生成入口;只保留能力矩阵、adapter 接口和后台开关。
### 0.3 当前技术基线
- 前台:Vite、React、TypeScript、React Router、TDesign、Tailwind、Zustand。
- 画布:现有 DOM/SVG 无限画布、节点 registry、图片工具和 ZIP/WebDAV 数据能力继续复用。
- 后台:现有 TDesign React Starter 继续作为管理台壳,替换模板 mock 页面和示例业务。
- 本地/容器同源:Nginx 将 `/api/*` 和 `/api/v1/ws/*` 反代到 `server:3100`;开发环境由 Vite 代理到同一服务。生产密钥仅通过运行环境注入。
- 服务端建议基线:Node.js + TypeScript、HTTP API、WebSocket 网关、PostgreSQL、Redis、任务队列、隔离的本地 staging、邮件/SMS/支付适配器。对象存储 adapter 预留但 V1 默认关闭。具体框架可以在技术评审时确定,但领域边界和接口契约先按本文执行。
- 外部模型规范:一期统一使用 OpenAI 兼容图片接口作为规范化入口;其他供应商通过服务端 adapter 转换,不向前台暴露差异。
- 用户端模板:`docs/design-reference/MiragenFlow-front/` 只作为设计和组件输入;不得让运行代码从该参考目录跨层引用。
## 1. 前台产品范围
前台用户只负责创作、查看自己的任务和余额、管理自己的资产/存储。渠道、供应商账号、价格表、路由优先级和健康状态全部由后台控制。
### 1.1 首页和工作台入口
- 保留网站首页,展示元境幻生定位、游戏美术/艺术资产/多视图工作流;3D 生成仅作为后续能力说明,不提供 V1 入口。
- 首页入口至少包括:开始创作、打开画布、查看资产、登录/注册、余额状态。
- 登录前可以浏览首页和公开能力说明;未登录提交生成任务时跳转登录/注册。
- 首页不展示供应商名、内部模型 ID、API Key 配置和渠道状态。
### 1.2 用户注册、登录和账户中心
一期用户端必须支持:
- 邮箱注册和邮箱验证码验证。
- 手机号注册和短信验证码验证;是否强制手机号由后台策略控制。
- V1 不接入 Google、Apple、微信等第三方 OAuth/社交登录。
- 密码登录、验证码登录(是否开放由后台策略控制)。
- Access Token + Refresh Token 会话。
- 用户两步验证默认关闭;后台开启后才要求用户完成 MFA,启用/关闭必须记录操作者、原因和生效时间。
- 退出登录、刷新会话、修改密码、忘记密码、重新发送验证邮件/短信。
- 账户状态:正常、待验证、冻结、注销中。
- 基本账户页:昵称、邮箱/手机号脱敏、余额、消费记录、任务历史、登录设备。
- 风险控制:验证码发送频率限制、图形验证码/人机校验、登录失败次数限制、IP/设备限流、异常会话注销;普通用户默认不展示验证挑战,开关开启后才执行。
认证安全基线固定如下:
- 生产环境使用同源会话;短期 Access Token 只保存在前端内存,Refresh Token 只通过 `HttpOnly`、`Secure`、`SameSite=Lax/Strict` Cookie 传输,不写入 `localStorage` 或画布导出文件。
- Access Token 必须包含明确的 `aud`、`sub`、`scope` 和过期时间;Refresh Token 采用轮换、哈希存储和复用检测,检测到旧 Token 重放时撤销同一设备会话链。
- Cookie 会话启用 CSRF 防护;跨域开发请求必须经过本地反向代理,不允许前端直接把凭证交给第三方域名。
- 邮箱和手机号先做规范化再建立唯一索引;验证码发送、消费和失败次数使用原子更新,验证码仅保存哈希。未完成验证的账户可以浏览公开页面,但不能调用会产生费用的任务接口。
- 密码使用成熟密码哈希算法(优先 Argon2id),记录算法版本;重置 Token 单次消费并在修改密码后撤销其他会话。账户注销通过 `POST /api/v1/me/close` 进入 `注销中`,由异步清理任务完成匿名化/删除。
- 前端在刷新会话时只允许一个刷新请求,其余请求等待同一结果;刷新失败后清空内存身份并回到登录页。
前台不再使用当前“浏览器本地空 user store”作为商业认证。`useUserStore` 改为服务端会话状态;登录成功后所有需要计费的 API 都必须携带用户身份。
### 1.3 公开模型产品目录
用户看到的是后台发布的产品目录,而不是渠道配置。
建议公开结构:
| 用户看到的选项 | 后台控制内容 |
| --- | --- |
| 基础模型 | 公开模型 ID、绑定的渠道分组、内部模型 ID、默认参数、单次价格、可用任务类型 |
| 高级模型 | 公开模型 ID、绑定的渠道分组、内部模型 ID、质量策略、单次价格、并发限制 |
| 旗舰模型 | 公开模型 ID、绑定的渠道分组、内部模型 ID、最高质量策略、单次价格、失败提示文案 |
| 分辨率 | 低/中/高/超高或后台自定义名称、实际像素尺寸、价格倍率、模型支持范围 |
| 生成数量 | 后台设置最大数量和阶梯价格 |
| 功能模式 | 文生图、图生图、局部编辑、反推提示词、多角度、抠图、拆分等 V1 能力开关;3D capability 仅保留禁用的预留开关 |
#### 模型 ID 可见性决策
一期固定采用“**显示公开模型 ID,不显示 provider 信息**”方案:
- 前台请求只携带公开的 `modelProductId`、`resolutionPresetId`、业务参数和幂等键。
- 前台最多显示后台配置的稳定公共模型 ID,例如 `basic-image-v1`;该 ID 与 provider 无关。
- 后台保存多个渠道的 `providerModelId`,用于调用、审计和故障排查;同一公开模型 ID 可以映射多个 provider 的不同内部 ID。
- 前台、用户导出文件和公开 API 均不得返回 provider 名称、Base URL、API Key、渠道顺序或 provider model ID。
- 管理员可以查看精确内部 ID;客服排障使用任务 ID 和 attempt ID,不要求用户知道供应商信息。
如果后续确认必须让专业用户看到模型信息,应只增加“公开别名/能力说明”,不要暴露渠道地址、Key、供应商账号或未经抽象的内部 ID。
### 1.4 无限画布工作台
保留并升级当前 `/canvas/:id`:
- 图片、文本、音频、生成配置、分组节点。
- 平移、缩放、框选、拖拽、调整尺寸、连线、分组、复制、删除、撤销/重做、小地图。
- 画布背景、节点标题、节点 JSON/信息查看、批量图片组。
- 画布项目创建、重命名、导入、导出、删除;项目级复制作为后续补充,当前不假设已实现。
- 画布内直接插入资产、上传图片/音频、粘贴剪贴板图片/文本。
- 任务节点展示排队、运行、成功、失败、取消、部分成功状态。
- 生成结果可以继续作为下一个节点的提示词、参考图或编辑输入。
一期要把当前“节点生成直接调用浏览器 API”改成“节点生成调用平台任务 API”,但保留当前节点数据结构和工作流表达方式,避免一次性重写画布交互。
### 1.5 游戏资产和艺术资产工作流
参考 Holopix 的功能理念,一期前台应提供以下产品能力入口。每项能力都应能从普通工具页或画布节点触发,并生成可回到画布/资产库的结果。
#### 通用生成和编辑
- 文生图、图生图、参考图编辑。
- 风格转换、构图参考、风格参考、主体参考。
- 万能渲染:统一承载构图、风格、参考和质量参数,而不是暴露供应商 API 差异。
- 局部细化、局部替换、擦除/重绘。
- 智能扩图/扩展画布。
- 相似图裂变/变体生成。
- 一键成稿、丰富细节、重绘放大。
- 反推提示词:从图片生成结构化、可再次执行的提示词结果。
#### 游戏资产专项
- 游戏角色、场景、道具、武器、ICON、UI 素材生成。
- 透明背景和前景抠图。
- Sprite Sheet/规则网格切分。
- 全能拆分:自动识别角色、道具、ICON、背景和可分离区域,输出透明子图、边界框、命名和关联组。
- 图层拆补:从一张合成图中恢复或重建局部图层。
- 线稿提取、材质/颜色参考和调色板生成。
- 像素图转换和像素风格变体。
- 表情生成或角色表情变体。
- 统一尺寸、命名、透明边缘和导出规格校验。
#### 多视图和 3D 化(V1 仅保留 2D 能力)
- 正视图、斜侧图、侧视图、俯视图、仰视图、背视图。
- 一键三视图、一键六视图,结果作为关联视图组。
- 自由视角:输入参考图后,使用水平角、俯仰角、相机距离、镜头范围控制视角。
- V1 不开放真正的单图/多图转 3D、文生 3D、图生 3D、3D 预览和模型导出;这些入口由 feature flag 关闭。
- V1 只实现多视图/自由视角的 2D 参考图任务,结果为关联图片组。
- 服务端保留 3D adapter、GLB/GLTF、OBJ、纹理和缩略图字段,待确认有稳定模型并通过生成、预览、导出验收后再启用。
当前画布可以复用为 2D 编排层;后续真正的 3D 节点和自由摄像机需要新增 Three.js/WebGL 视口,不能把当前“角度 prompt 重绘”包装成真实 3D。
### 1.6 音频能力
音频按既定范围保留:
- 文本生成语音。
- voice、格式、速度、instructions 参数。
- 音频任务进度、取消、失败重试、下载和画布节点引用。
- 音频文件进入统一媒体结果和 WebDAV 同步链路。
视频、首尾帧视频、图生视频、文生视频和动画时间轴不进入一期。
所有前台能力通过目录能力矩阵发布:每个 `modelProduct` 返回 `capabilities[]`、参数 schema、输入类型/大小、是否异步、结果类型和失败码映射。前台只渲染当前产品声明的控件;当能力未配置或版本失效时显示“暂不可用”,不自行猜测 provider 参数。图片、音频和 V1 多视图结果统一关联 `taskId`、`outputId`、资产/画布引用和保留期;3D 结果字段只做接口预留。
### 1.7 资产、历史和存储
- 我的资产:图片、文本,后续可扩展音频、3D、Sprite、序列帧和模型。
- 搜索、标签、类型筛选、预览、编辑、复制、下载、删除、画布插入。
- 作品/任务历史:按项目、任务类型、模型产品、时间、状态筛选。
- 生成结果版本:保留输入参数、公开模型产品、分辨率、任务 ID 和输出关联,不暴露供应商凭证。
- 本地:画布、节点、资产索引和已保存媒体默认写入浏览器 IndexedDB/localForage,按用户命名空间隔离;认证 Refresh Token、API Key 和 WebDAV 密码不得进入本地业务存储。
- WebDAV:用户配置并同步画布、资产、图片、音频及后续 3D/序列文件。同步使用每用户命名空间、manifest 版本、校验和和软删除标记;同一资源发生双向修改时保留冲突副本并提示用户选择,不静默覆盖。
- WebDAV 凭证在服务端加密保存或使用 KMS 引用,前台只能看到脱敏连接状态;Base URL 做 HTTPS/allowlist/私网阻断和路径规范化,连接失败进入可重试的离线队列,不阻塞生成任务主链路。
- 平台侧 V1 只保存任务元数据、账本和必要的临时 staging 结果;staging 位于静态目录之外,使用随机对象键、所有权校验、TTL、软删除和 GC 状态。对象存储 adapter 预留但默认关闭,后续接入不改变资产/任务接口。
- 后台可视化配置任务结果、原图和 WebDAV manifest 的保留时长、归档策略和最大延长次数;用户可以在上限内手动延长,超过上限需要后台权限或套餐策略。归档优先写入 WebDAV,失败时保留待处理状态,不静默丢失。
- 用户可以在权限和保留策略允许的范围内主动删除任务结果、原图和自己的 WebDAV manifest;删除先写软删除/审计事件,再由 GC 清理平台 staging,WebDAV 删除失败进入重试队列并显示状态。
### 1.8 余额和消费展示
- 右上角或账户中心显示统一余额单位,V1 默认展示“金币”文字和金币图标;前台不出现“积分”字样。
- 余额单位由后台配置名称、短代码、图标 key、符号、精度和显示小数位;后续可以切换为其他文字单位或图标单位,但同一生效版本只能有一个用户可用单位。
- 充值金额通过后台发布的换算比例转为金币,例如支付货币 `amount` -> `balanceUnitAmount`;换算比例、舍入方式、最低充值和生效版本都进入订单快照。
- 提交任务前显示预计消耗。
- 批量生成显示按数量和分辨率计算的预计消耗。
- 任务详情显示预扣、实际扣除、释放/退款状态。
- 余额不足时阻止提交并跳转充值,不创建不可执行任务。
- 用户可以查看充值订单、消费账单和退款/释放记录,但不能修改账本。
- 用户可以购买后台发布的套餐;套餐可包含赠送金币、购买价格、有效时长、并发限制、队列优先级和可用渠道组。套餐余额和普通充值余额都进入同一账本,但来源和过期策略必须分开记录。
### 1.9 用户侧错误和可用性提示
用户不能看到供应商内部故障细节,但必须得到可执行提示:
- 当前模型不可用,请切换到其他旗舰模型。
- 余额不足,请充值后重试。
- 当前分辨率不支持该模型,请降低分辨率或切换模型。
- 请求参数无效,请修改提示词/参考图。
- 任务已取消,预扣余额已释放。
- 任务部分成功,仅对成功结果扣费。
- 系统正在排队,显示任务编号和预计状态,不重复提交。
内部日志可以保留 provider、channel、attempt、HTTP 状态和响应摘要,但前台只显示公共错误码、任务 ID 和建议动作。
## 2. 后台管理范围
后台仅管理员可用,地址保留 `/admin/`。TDesign 模板中的 Dashboard、List、Form、Detail、User、Result 页面可以继续作为视觉和路由壳,但所有示例 mock、Tencent 文案、模板用户数据和模板接口必须替换为真实业务域。
### 2.1 管理员认证和权限
- 管理员登录、退出、刷新会话。
- 管理员使用独立认证域和独立会话 Cookie;管理员 Access Token 的 `aud` 不得被用户端 API 接受,`/admin/` 静态路径本身不视为权限边界,所有 `/api/v1/admin/*` 请求都必须经过服务端鉴权。
- 管理员角色:至少 `super_admin`、`operator`、`finance`、`support`、`auditor`。
- 权限粒度:用户、认证消息、渠道、模型产品、任务、余额/订单、系统配置、审计日志;默认拒绝,按角色授予最小权限,并对用户、任务、账单等对象做范围校验。
- 高风险操作二次确认:禁用渠道、调整余额、退款、删除用户、修改价格和切换路由优先级。
- 管理员操作写入审计日志,记录操作者、对象、前后值、IP、请求 ID 和时间。
管理员安全基线:
- 高风险操作必须重新认证;MFA、IP 白名单和设备策略由后台开关控制,默认关闭增强项。管理员登录、权限变更、密钥查看/轮换和高风险操作均写入不可变审计记录;管理员未开启增强策略时只需邮箱和密码。
- 人工调账和支付退款采用“申请 -> 审批 -> 执行”状态机,申请人和审批人不能是同一账号;没有审批记录不得执行。
- 管理员列表和配置写入使用 `Idempotency-Key`、资源版本号/`If-Match` 做幂等和乐观锁,版本冲突返回 `409`,不能静默覆盖其他管理员的变更。
- `support` 默认不能查看完整提示词、原图、WebDAV 凭证或渠道密钥;临时 break-glass 授权需要审批、过期时间、脱敏展示和独立审计。
### 2.2 用户管理
管理员可以:
- 按用户 ID、邮箱、手机号、状态、注册时间、余额和最近活动搜索。
- 查看用户基本资料、验证状态、会话、登录设备、任务历史、消费和充值记录。
- 冻结/解冻账户、触发密码重置、重新发送验证消息。
- 手动增加/扣减余额,但必须通过“人工账本调整”记录原因和审批人。
- 设置用户等级、限流、并发数、每日额度和可见模型产品。
- 查看用户是否配置 WebDAV,但不能明文查看用户 WebDAV 密码。
### 2.3 注册、认证、邮件和短信管理
后台配置并监控:
- 邮件供应商:SMTP/第三方邮件 API、发件人、模板、域名状态。
- 短信供应商:供应商、签名、模板、区域和发送策略。
- 验证模板:注册验证、登录验证码、密码重置、异常登录提醒、余额/订单通知。
- 消息发送日志:待发送、发送中、成功、失败、重试次数、供应商响应摘要。
- 验证码策略:有效期、发送冷却、每日上限、失败次数、IP/设备/目标限制、图形验证码或人机挑战开关。防刷策略为一期必做项,不得只依赖前端按钮禁用。
- 两步验证策略:用户默认关闭,管理员保持独立登录流程,MFA 默认关闭并由后台安全开关启用。后台提供启用/关闭、重置、恢复码和生效范围配置,策略变更必须二次确认并写审计。
- Provider 故障切换:邮件/SMS 也使用 outbox + 重试,不阻塞用户注册主事务。
验证码必须只保存哈希或不可逆摘要,不保存明文;敏感信息不得写入普通日志。
验证码的目标(邮箱/手机号)需规范化后参与限流键;消费操作必须使用一次性原子更新(未过期、未使用、尝试次数未超限),并记录发送 IP、设备和 provider message ID,重复消费统一返回验证失败而不改变账户状态。
### 2.4 渠道管理
渠道是供应商账号或接口实例,不是用户看到的模型产品。
单个渠道最少包含:
- `channelId`、名称、供应商、环境、区域。
- Base URL、API 格式、认证方式、加密后的 API Key/Secret。
- 支持的能力:image/text/audio/3D/utility。
- 可用 provider model ID 映射。
- 超时、最大并发、速率限制、单次重试次数。
- 启用/禁用状态、管理员备注、维护窗口。
- 健康状态、连续失败次数、熔断状态、最近成功/失败时间。
- 成本估算、供应商计费单位和内部成本备注。
渠道安全要求:Base URL 只允许 HTTPS 和后台配置的域名/IP allowlist,阻断 loopback、link-local、RFC1918、Unix socket 和重定向到私网;API Key/Secret 使用 KMS 或部署密钥加密并带版本号,轮换时保留旧版本到在途 attempt 结束,前台、审计日志和错误响应均不得出现明文凭证。
后台操作:新增、编辑、测试、启用、禁用、轮换凭证、查看脱敏健康信息、查看调用统计和失败原因。
### 2.5 渠道分组和路由顺序
分组是用户请求所映射的内部路由池,例如:
```text
旗舰图片组
1. Provider-A 账号 1 -> providerModelId=MODEL_A
2. Provider-B 账号 2 -> providerModelId=MODEL_B
3. Provider-C 账号 1 -> providerModelId=MODEL_C
4. Provider-D 账号 4 -> providerModelId=MODEL_D
```
分组配置:
- `groupId`、内部名称、能力、用途和维护说明。
- 成员渠道及明确的 priority 顺序。
- 是否允许自动故障切换。
- 组级超时、重试上限、并发和熔断策略。
- 组级公共错误文案和推荐替代模型产品。
- 绑定的公开模型产品和分辨率策略。
- 配置发布版本、修改人和生效时间;每次发布生成不可变版本,支持回滚到上一版本。
- 失败分类白名单、每渠道 retry budget、退避初始值/上限/抖动、熔断阈值、半开探活间隔和任务 lease 超时。
默认路由规则:
1. 创建任务时把 `modelProduct`、分辨率、价格、渠道组、绑定关系和路由策略的发布版本全部写入任务快照;任务排队期间后台改价、改 priority 或下架产品,不改变该任务的计费和路由依据。
2. 按快照中的 priority 从小到大选择启用且未熔断的渠道;渠道启停只影响尚未创建快照的新任务,已创建任务仅在安全策略允许时跳过明确禁用的渠道。
3. 每次调用都创建一个 `attempt`,状态至少为 `pending -> sent -> succeeded/failed/unknown/canceled`;写入 worker lease、provider request ID、平台幂等键和超时原因。队列使用可见性超时、心跳和死信队列,worker 崩溃后由恢复任务接管。
4. 单渠道发生可重试错误时,按组级 retry budget、指数退避和抖动策略重试;达到该渠道预算后切到下一渠道。供应商已接受请求但客户端超时的 `unknown` 结果先按 provider request ID 查询/对账,不直接重复提交。
5. 熔断计数、半开探活和并发占用使用 Redis 原子操作;熔断状态包含 `closed/open/half_open`、版本和过期时间,只有探活成功才能恢复。管理员手动启停或探活结果都写健康事件。
6. 401/403/模型不存在按“渠道凭证/模型配置错误”处理:隔离该渠道并告警;若请求本身被策略拒绝,不切换渠道。用户参数错误、内容审核拒绝、图片格式无效等不可重试错误直接结束任务。
7. 组内全部渠道不可用时返回公共错误 `MODEL_GROUP_UNAVAILABLE`,提示用户切换同档位其他模型;除非后台明确设置 `fallbackGroupId`,否则不从旗舰组静默降级到高级组或基础模型。
8. 渠道切换对用户透明,任务 ID 不变;后台任务详情展示所有 attempt。用户取消与 worker/供应商完成竞态时,以服务端先提交的终态为准,迟到结果只做对账,不重复入账或覆盖已取消状态。
### 2.6 模型产品和分辨率配置
管理员要管理“用户看到的模型”而不是只管理渠道:
- 公开模型产品:基础、高级、旗舰,以及抠图、拆分、线稿等 V1 专项产品;3D 产品只保留后台草稿/契约,不在 V1 上架。
- 公共名称、公开模型 ID、描述、图标、能力标签、排序、上架状态。
- 绑定的 `channelGroupId`。
- 可选分辨率预设:低、中、高、超高/4K,实际宽高、比例、模型限制。
- 默认质量、最大生成数量、参考图数量、支持 mask 与否。
- 每种“模型产品 + 分辨率 + 功能”的公开价格/余额消耗。
- 替代模型建议:同档位优先,其次由后台选择允许的跨档位推荐。
- 发布版本和生效时间;修改价格或路由需写审计日志。
套餐和队列策略由后台单独配置,不把 provider 信息暴露给用户:
- 套餐字段:`planId`、套餐名称、公共编码、图标、基本介绍、套餐时长、购买价格、包含金币、有效期、上架状态、排序、发布版本。
- 套餐权益:允许使用的公开模型产品,以及后台内部的 `allowedChannelGroupIds`、并发上限、队列优先级、单文件大小、结果保留上限和是否允许延长/归档;渠道组 ID 只存于后台权益快照,不返回用户端。
- V1 不限制每日任务数;并发数、队列优先级和套餐可用范围必须限制,并在任务创建时写入权益快照。
- 用户端只展示套餐名称、价格、金币数量、时长、公开模型/能力范围和权益说明;不显示 provider 分组、账号或内部渠道顺序。
- 套餐可停用但不删除历史版本;已购买权益按购买时版本结算,新增任务按当前发布版本校验。
前台目录 API 只返回这些公开字段,不返回 `channelId`、`providerModelId`、Base URL、Key、内部成本和渠道顺序。
### 2.7 任务中心和接口调用监控
后台可以查看:
- 任务 ID、用户、公开模型产品、功能、分辨率、数量、状态、余额状态。
- `queued/running/succeeded/partial/failed/canceled/refunded` 状态变化。
- 每次 provider attempt、渠道、开始/结束时间、HTTP 状态、错误分类和重试结果。
- 平均耗时、成功率、P50/P95 延迟、渠道错误率、模型组可用率。
- 取消任务、重试任务、标记异常、查看脱敏请求/响应摘要。
- 查看 WebSocket 连接数、心跳、断线重连、事件积压和消费延迟;任务事件以 `taskId + eventId + sequence` 去重。
- 不允许管理员在任务页面直接查看用户 API Key、完整提示词附件或敏感凭证,除非有明确权限和审计。
### 2.8 余额、账本、充值和支付预留
计费方式统一为余额制:
- 充值成功:按订单快照中的换算比例增加统一余额单位(V1 默认金币)。
- 任务提交:预扣预计余额。
- 任务成功:按实际成功输出结算。
- 任务取消、全渠道失败或系统错误:释放预扣或产生退款账本记录。
- 批量任务部分成功:只扣成功结果,失败项释放预扣。
- 同一任务的 provider 重试不向用户重复收费。
金额必须使用整数最小单位或定点 Decimal,禁止使用浮点数直接计算余额。余额不可直接覆盖,只能追加账本流水:
```text
balance_accounts
balance_ledger
-> reserve 预扣
-> settle 成功结算
-> release 释放预扣
-> refund 退款
-> manual_adj 管理员人工调整
recharge_orders
payment_events
```
支付接口只做适配层预留:
- `createRechargeOrder(userId, amount, provider)`。
- `queryPayment(orderId)`。
- `handlePaymentWebhook(provider, signature, payload)`。
- `refundPayment(orderId, amount, reason)`。
- 支付回调签名校验、幂等键、订单状态机和重复通知处理。
余额单位和换算配置必须可视化管理:
- 余额单位配置:名称、短代码、图标 key、符号、精度、显示小数位、是否启用。
- 换算规则配置:支付货币、余额单位、兑换比例、舍入模式、最低/最高充值、赠送规则、版本和生效时间。
- 价格和套餐金额以余额最小单位保存;充值订单同时保存支付金额、余额到账金额和规则版本,避免后续改比例影响历史订单。
一期充值只提供管理员人工充值和 mock provider;不能用“收到前端 success 参数”直接加余额。真实支付供应商在后续接入时只实现 adapter,不改余额账本规则。支付 API 和 webhook 契约必须先预留,等待用户提供第三方支付开发文档。
套餐后台页面必须支持:新增/编辑/复制/上架/下架、名称、公共编码、图标、介绍、套餐时长、包含金币、购买价格、可用模型产品/渠道组、并发上限、队列优先级、结果保留上限和版本回滚。套餐购买订单与普通充值订单分开记录,但到账仍写入统一余额账本。
### 2.9 系统配置和审计
- 邮件/SMS 供应商、验证码策略。
- 模型产品、渠道组、渠道健康阈值、价格和限流。
- 余额单位、金币图标/文字、换算比例、舍入和充值上下限。
- 套餐名称、时长、购买价格、包含金币、上架状态、介绍、可用模型/渠道组、并发和队列优先级。
- 余额/订单/支付开关。
- 本地 staging、WebDAV、对象存储 adapter 开关、任务/原图/manifest 保留期、归档和用户延长上限。
- 全部敏感配置加密或通过部署环境注入。
- 审计日志采用 append-only 存储,至少保存链式摘要/防篡改校验、保留期、脱敏策略和导出权限;审计日志自身的读取/导出也必须产生审计记录。
- 审计日志支持按管理员、对象、操作类型、请求 ID 查询和导出;任务、支付、消息和 provider 请求贯穿同一 `requestId/correlationId`,便于追踪一次调用的全部状态。
## 3. 服务端调用和路由逻辑
### 3.1 前台提交任务
前台统一调用平台 API,不再调用供应商地址:
```text
POST /api/v1/tasks/image
Authorization: Bearer ACCESS_TOKEN
Idempotency-Key: CLIENT_GENERATED_KEY
{
"modelProductId": "flagship-image",
"resolutionPresetId": "high",
"prompt": "...",
"references": [...],
"mask": ...,
"count": 4,
"canvasProjectId": "..."
}
```
服务端顺序:
1. 校验 Access Token、账户状态、产品是否对该用户可见。
2. 校验提示词、参考图、分辨率、数量和功能参数。
3. 校验引用文件、mask 和画布项目属于当前用户,检查 MIME、大小、像素、数量、病毒/恶意内容扫描状态和引用有效期;不接受任意外部 URL 直接进入 provider。
4. 读取模型产品、分辨率价格、绑定分组;不信任前端传来的价格或 provider model ID,并把目录、价格、分辨率、渠道组和路由策略版本复制到任务快照。
5. 解析用户当前有效套餐,检查公开模型/内部渠道组权益、余额、并发和队列优先级;每日任务数 V1 不设上限。
6. 使用幂等键创建任务并预扣余额;重复请求返回原任务,不重复预扣。
7. 将任务放入队列,返回任务 ID、状态和预计消耗。
### 3.2 队列和 provider attempt
```text
generation_task
-> resolve modelProduct
-> resolve channelGroup
-> ordered channels
-> provider attempt #1
success -> normalize result -> store output -> settle
retryable failure -> attempt #2
-> provider attempt #2 ...
-> all unavailable -> fail public error -> release reserve
```
任务应支持:
- HTTP 查询 `GET /api/v1/tasks/:id`。
- WebSocket 是 V1 长任务进度主通道:连接使用用户会话鉴权、心跳、订阅/取消订阅和 `taskId` 权限校验;事件带递增 `sequence`、`taskId`、`attemptId` 和 `eventId`,客户端通过 cursor/last sequence 断线重放,服务端以任务历史快照为权威并按 eventId 去重。HTTP 轮询仅作为断线或不支持 WS 客户端的降级方案,SSE 不作为一期主通道。
- `POST /api/v1/tasks/:id/cancel` 取消排队或可取消的运行任务;若 provider 支持取消则发送取消请求,否则等待未知结果对账,不能因迟到响应重复结算。
- 任务完成后返回结果元数据、缩略图/签名 URL、画布关联信息和资产保存入口;结果下载必须校验用户所有权和资源 scope。
- 任务结果存储采用短期签名对象 URL,URL 绑定 `userId/taskId/outputId`、用途和过期时间,可主动撤销;保存到资产或 WebDAV 后创建持久化引用,清理任务回收未保存结果。
服务端与 provider 使用统一 adapter 契约:
- 输入至少包含 `taskType`、规范化参数、引用对象、超时、取消信号和平台幂等键;adapter 负责把它转换成供应商请求,不把密钥、Base URL 或原始响应传回前台。
- 输出统一为 `queued/running/succeeded/partial/failed/unknown/canceled`、标准化 `outputs[]`、成本/用量摘要、provider request ID 和可审计错误分类。V1 的 image、text、audio、2D utility 可以有各自参数;3D adapter 只保留契约,启用后也必须遵守同一任务/attempt/结果生命周期。
- adapter 必须限制出站超时、响应大小和 MIME,屏蔽供应商提示词/凭证泄露;管理员配置的 Base URL 经过 HTTPS、域名/IP allowlist 和私网地址阻断,禁止 SSRF。
### 3.3 错误分类
| 错误类别 | 示例 | 行为 |
| --- | --- | --- |
| 用户参数错误 | 尺寸非法、参考图格式错误、提示词缺失 | 直接失败,不切换渠道,不扣费。 |
| 内容/策略拒绝 | provider 返回内容审核拒绝 | 直接失败,禁止切换渠道;该输出不计费,未使用的预扣全部 `release`,记录公共拒绝码。 |
| 渠道暂时不可用 | 超时、网络错误、429、502、503、供应商维护 | 记录 attempt,按顺序切换后续渠道。 |
| 渠道凭证/配置错误 | 401、403、模型不存在 | 标记渠道健康异常,切换后续渠道;管理员收到告警。 |
| 系统错误 | 队列、存储、账本事务失败 | 任务进入系统失败,释放预扣并记录告警。 |
| 全组不可用 | 所有渠道耗尽或全部熔断 | 返回 `MODEL_GROUP_UNAVAILABLE`,建议切换其他公开模型。 |
用户消息只使用公共错误码和可执行建议;provider 原文只在后台脱敏日志中保存。
`401/403` 只有在确认属于渠道凭证/权限配置错误时才隔离渠道;若是用户内容、租户权限或产品策略拒绝,按用户参数错误处理,不把同一请求扩散到其他供应商。所有 attempt 的原始响应先脱敏再写入日志,禁止保存完整 API Key、Cookie、Authorization、原图和未授权的 WebDAV 凭证。
### 3.4 余额结算规则
- 预扣发生在任务入队前,余额不足不入队。
- 预扣金额以公开模型产品、分辨率、数量和功能参数计算,provider 切换不改变用户价格。
- 成功输出逐项结算;一张失败图不应让整批成功图重复或多扣。
- provider 重试属于平台成本,不向用户重复生成多条扣费记录。
- 任务超时、取消、全渠道失败必须产生 release/refund 账本记录。
- 所有账本写入和任务状态变化必须具备事务边界和幂等约束。
账本不变量和状态转移:
- 账户永远满足 `available + reserved = ledger_confirmed_balance`,`available >= 0`、`reserved >= 0`;所有金额使用同一币种和整数最小单位/Decimal,流水金额正负方向固定并在 API 中明确。
- V1 账本以余额单位最小整数(默认金币)记账;支付货币只出现在充值订单和换算规则中。任务价格、套餐到账和人工调账都必须保存单位版本,禁止在账本层混用支付货币与余额单位。
- `reserve` 只允许从 `available` 转入 `reserved`,`settle` 从 `reserved` 转为实际消费,`release` 把未使用部分转回 `available`;`refund` 仅表示已结算消费的补回,不等同于预扣释放,也不直接代表支付渠道退款。
- 预扣按后台定义的消费顺序(默认优先使用最早到期的套餐/赠送批次)分配到 `balance_buckets`,释放时按原批次返还;任务快照记录 bucket allocation,避免套餐过期或换算比例变化造成错扣。
- 每个任务/输出最多一条生效的 reserve、settle、release 或 refund 关系;数据库唯一约束和 `Idempotency-Key` 共同防止重复记账。任务状态和账本状态在同一事务中提交,或由带版本的 outbox/reconciler 可证明地补偿。
- 预扣带 `expiresAt`;超时由 reconciler 扫描并根据 attempt/任务最终状态执行 release 或进入人工对账,不允许静默丢失冻结余额。余额更新使用行锁或乐观版本 CAS,冲突重试后仍失败则任务不入队。
- 批量任务按输出保存 `unitPriceSnapshot` 和 `chargedAmount`;成功输出逐项 settle,失败/重复/未知输出不重复扣费。provider 成本与用户价格分离,provider 重试只记录平台成本。
支付订单与回调状态至少为 `created -> pending -> paid/failed/expired/refunding/refunded`。`payment_events` 以供应商事件 ID 唯一,校验签名、订单号、金额、币种和用户后再入账;乱序/重复通知按状态机幂等处理,另有定时对账和拒付/退款补偿任务。
## 4. 最小领域数据模型
以下是一期需要在服务端落地的领域,不要求一次采用完全相同的表名,但关系和约束必须保留。
### 4.1 用户和认证
- `users`:用户主表、状态、昵称、注册时间、最后活动。
- `user_identities`:邮箱/手机号、验证状态、唯一索引、脱敏展示字段。
- `password_credentials`:密码哈希、算法版本、修改时间。
- `verification_codes`:用途、目标、哈希、过期时间、尝试次数、发送来源。
- `sessions`:用户/管理员会话域、refresh token 哈希、设备、IP、audience、过期、轮换链和撤销时间。
- `user_mfa_factors`:用户/管理员身份、因子类型、密钥/恢复码摘要、启用状态和最近使用时间;密钥材料加密或只保存不可逆摘要。
- `captcha_challenges`:目标、IP/设备指纹、挑战类型、哈希结果、过期时间、消费状态和失败次数。
- `admin_roles` / `admin_permissions` / `admin_user_roles`:后台 RBAC。
### 4.2 模型和渠道
- `model_products`:用户看到的基础/高级/旗舰及专项产品。
- `model_product_resolutions`:公开分辨率、实际像素、倍率、能力限制。
- `channel_groups`:分组策略、优先级、熔断和公共错误配置、发布版本和生效时间。
- `provider_channels`:供应商账号、加密凭证、Base URL、状态和限流。
- `channel_bindings`:组成员顺序、provider model ID、参数映射。
- `channel_health`:成功率、连续失败、熔断开始/结束、最近探活。
- `pricing_rules`:模型产品/分辨率/功能/数量的公开价格和生效版本。
- `membership_plans`:套餐名称、公共编码、图标、介绍、时长、购买价格、包含金币、上架状态、可用模型/渠道组、并发、队列优先级、保留上限和版本。
- `plan_purchases`:用户、套餐版本、支付金额、到账金币、有效期、权益快照和状态。
### 4.3 任务和结果
- `generation_tasks`:用户、公开模型、功能、参数摘要、状态、幂等键、预扣金额、余额单位版本、产品/分辨率/价格/渠道组/路由/套餐权益快照版本、状态版本、lease、队列优先级和结果保留期。
- `generation_attempts`:任务、渠道、provider model、开始/结束、错误分类、重试序号、attempt 状态、worker lease、平台幂等键、provider request ID、unknown 对账信息。
- `generation_outputs`:结果文件、缩略图、MIME、尺寸、成功/失败、单位价格快照、实际扣费、资源 scope、签名 URL 过期和保留期。
- `upload_objects`:用户、对象 key、MIME、大小、校验和、扫描状态、来源、过期时间和软删除时间;所有参考图/mask/资产内容先经过该对象层。
- `canvas_projects` / `canvas_nodes` / `assets`:如果一期把项目和资产同步到云端,则与用户隔离;若暂时保持浏览器本地,也必须保存任务和资产关联 ID。
### 4.4 余额和支付
- `balance_accounts`:用户余额、冻结/预扣余额、版本号。
- `balance_buckets`:充值/套餐到账批次、剩余余额、有效期、消费顺序;过期批次由 GC/账本任务处理,不能直接覆盖账户总额。
- `balance_ledger`:不可变流水、类型、金额、余额单位版本、来源(充值/套餐/任务/调账)、关联任务/订单、有效期、幂等键。
- `balance_units`:单位名称、短代码、图标 key、符号、精度、显示小数位和状态。
- `balance_conversion_rules`:支付货币、余额单位、兑换比例、舍入、上下限、赠送规则、版本和生效时间。
- `recharge_orders`:用户、金额、支付渠道、状态、过期时间。
- `payment_events`:供应商事件 ID、签名校验结果、原始摘要、处理状态。
- `refund_records`:退款金额、原因、原订单、支付状态。
### 4.5 消息和审计
- `message_providers`:邮件/SMS 供应商和加密配置。
- `message_templates`:注册、验证、重置、通知模板和版本。
- `message_outbox`:异步发送状态、重试和 provider message ID。
- `audit_logs`:管理员、操作、对象、前后值摘要、IP、请求 ID。
- `storage_policies`:任务结果、原图、WebDAV manifest 的保留期、归档策略、用户延长上限和 GC 规则。
### 4.6 存储和同步
- `webdav_connections`:用户、加密凭证引用、规范化 Base URL、根目录命名空间、最近测试和轮换时间;读取接口只返回脱敏信息。
- `sync_manifests`:用户、资源类型、版本、校验和、更新时间、冲突状态和最后同步游标。
- `canvas_projects`、`assets` 和 `upload_objects` 都必须带 `ownerId`;对象访问、下载、任务引用和 WebDAV 同步均做所有权校验,禁止通过可猜测 ID 跨用户读取。
### 4.7 团队扩展预留(V1 不启用)
- `organizations` / `teams`:未来的工作空间、所有者、套餐/余额归属和状态;V1 不创建团队业务记录。
- `organization_members`:未来的成员、角色、邀请状态和加入/退出时间;V1 不开放邀请和共享操作。
- `resource_scopes`:未来为画布、资产、任务和对象增加 `ownerType/ownerId` 范围字段;V1 固定为用户所有权,预留字段不能改变当前的越权校验。
- 未来启用团队时,必须先定义共享资产、团队余额、成员审计和对象级权限,再开放 `/organizations/*` API。
## 5. API 边界规划
### 5.1 用户公开/认证 API
```text
POST /api/v1/auth/register
POST /api/v1/auth/challenge
GET /api/v1/auth/policy
POST /api/v1/auth/verify-email
POST /api/v1/auth/verify-sms
POST /api/v1/auth/login
POST /api/v1/auth/refresh
POST /api/v1/auth/logout
POST /api/v1/auth/password/forgot
POST /api/v1/auth/password/reset
POST /api/v1/auth/password/change
POST /api/v1/auth/verification/resend
POST /api/v1/auth/mfa/setup
POST /api/v1/auth/mfa/verify
POST /api/v1/auth/mfa/disable
POST /api/v1/auth/mfa/recovery
POST /api/v1/me/close
GET /api/v1/me
GET /api/v1/me/plans
GET /api/v1/me/entitlements
GET /api/v1/me/sessions
DELETE /api/v1/me/sessions/:id
```
### 5.2 用户目录、任务、资产和余额 API
```text
GET /api/v1/catalog/models
GET /api/v1/catalog/models/:id
GET /api/v1/catalog/balance-unit
GET /api/v1/catalog/plans
GET /api/v1/catalog/plans/:id
POST /api/v1/tasks/image
POST /api/v1/tasks/text
POST /api/v1/tasks/audio
POST /api/v1/tasks/image/reverse-prompt
POST /api/v1/tasks/image/multi-angle
POST /api/v1/tasks/image/matting
POST /api/v1/tasks/image/split
POST /api/v1/tasks/image/upscale
POST /api/v1/tasks/image/expand
POST /api/v1/tasks/3d
GET /api/v1/tasks
GET /api/v1/tasks/:id
GET /api/v1/tasks/:id/events # 事件历史/cursor 重放,不是 SSE
WS /api/v1/ws/tasks
POST /api/v1/tasks/:id/cancel
GET /api/v1/balance
GET /api/v1/balance/ledger
POST /api/v1/recharge/orders
GET /api/v1/recharge/orders/:id
POST /api/v1/recharge/plan-orders
GET /api/v1/recharge/plan-orders/:id
GET /api/v1/assets
POST /api/v1/assets
PATCH /api/v1/assets/:id
DELETE /api/v1/assets/:id
POST /api/v1/uploads/presign
POST /api/v1/uploads/:id/complete
GET /api/v1/uploads/:id/download
GET /api/v1/me/webdav
PUT /api/v1/me/webdav
POST /api/v1/me/webdav/test
POST /api/v1/me/webdav/sync
GET /api/v1/me/webdav/sync-status
```
图片专项 API 可以先统一映射到一个 `taskType`,不要求每个功能都复制一套 provider 调用代码。裁剪等纯本地操作可以继续在前台执行,但凡涉及模型或扣费的能力必须经过任务网关。
`POST /api/v1/tasks/3d` 仅作为禁用状态的契约预留;V1 目录不发布 3D capability,调用时返回统一的 `CAPABILITY_NOT_ENABLED`,不能把 2D 多角度结果伪装成 3D 文件。
一期固定以浏览器本地画布/资产 + WebDAV 为用户内容的持久化方式,服务端只保存任务、余额、结果引用和必要的资产关联;云端 `canvas/projects` CRUD 不进入 V1,仅保留未来扩展契约。
上传接口只返回平台对象 ID,不接受任意外部 URL;完成上传时服务端重新校验大小、MIME、校验和、扫描状态和用户所有权。WebDAV 接口保存加密凭证引用,Base URL 必须通过 HTTPS、域名/IP allowlist 和私网地址阻断,远端路径固定在每个用户的命名空间内,禁止 `..`、绝对路径和跨用户 manifest。
资产写入至少包含 `kind`、`title`、`tags`、`sourceTaskId`、`sourceOutputId` 和 `objectId`/文本内容;服务端生成下载授权并校验软删除状态。任务结果保存到资产与账本结算必须有明确的关联 ID,重复保存请求返回同一资产而不是创建副本。
### 5.3 管理员 API
```text
POST /api/v1/admin/auth/login
POST /api/v1/admin/auth/refresh
POST /api/v1/admin/auth/logout
POST /api/v1/admin/auth/mfa/setup
POST /api/v1/admin/auth/mfa/verify
POST /api/v1/admin/auth/mfa/disable
GET/PATCH /api/v1/admin/users
POST /api/v1/admin/users/:id/freeze
POST /api/v1/admin/users/:id/balance-adjustments
GET/POST/PATCH /api/v1/admin/message-providers
GET/POST/PATCH /api/v1/admin/message-templates
GET /api/v1/admin/message-outbox
GET/POST/PATCH /api/v1/admin/channels
POST /api/v1/admin/channels/:id/test
POST /api/v1/admin/channels/:id/rotate-secret
GET/POST/PATCH /api/v1/admin/channel-groups
PATCH /api/v1/admin/channel-groups/:id/order
GET /api/v1/admin/channel-health
GET/POST/PATCH /api/v1/admin/model-products
GET/POST/PATCH /api/v1/admin/model-products/:id/resolutions
GET/POST/PATCH /api/v1/admin/pricing-rules
GET/POST/PATCH /api/v1/admin/billing/units
GET/POST/PATCH /api/v1/admin/billing/conversion-rules
GET/POST/PATCH /api/v1/admin/membership-plans
POST /api/v1/admin/membership-plans/:id/publish
POST /api/v1/admin/membership-plans/:id/rollback
GET /api/v1/admin/tasks
GET /api/v1/admin/tasks/:id/attempts
POST /api/v1/admin/tasks/:id/retry
POST /api/v1/admin/tasks/:id/cancel
GET /api/v1/admin/balance/ledger
GET/POST/PATCH /api/v1/admin/recharge-orders
GET/POST/PATCH /api/v1/admin/payment-providers
GET /api/v1/admin/payment-events
GET/POST/PATCH /api/v1/admin/storage-policies
GET /api/v1/admin/ws/metrics
GET /api/v1/admin/audit-logs
```
所有管理员写操作都需要权限检查、请求 ID、审计日志和幂等处理。
## 6. 后台页面规划
### 6.1 总览 Dashboard
- 注册用户、活跃用户、余额总额、充值金额、生成任务数。
- 各模型产品成功率、P95 延迟、失败率和消耗。
- 渠道组健康度、熔断渠道、当前告警。
- 邮件/SMS 成功率、支付回调异常、队列积压。
### 6.2 用户与认证
- 用户列表、用户详情、身份验证状态、登录设备和会话。
- 冻结/解冻、重置密码、验证消息重发。
- 用户模型可见范围、额度、并发和余额调整。
- 注册策略、验证码策略、邮件/SMS provider、模板和发送日志。
### 6.3 模型与渠道
- 模型产品列表:基础/高级/旗舰/专项能力。
- 分辨率和数量配置、价格、上架/下架、替代模型建议。
- 渠道列表:凭证脱敏、测试、启停、健康、成本、限流。
- 渠道分组:成员顺序、绑定模型 ID、熔断策略、公共不可用提示。
- 变更预览:修改路由或价格前显示影响范围。
### 6.4 任务、余额与支付
- 任务列表、任务详情、attempt 时间线、结果和扣费状态。
- 余额单位/金币图标、换算比例、舍入和充值上下限。
- 套餐管理:名称、编码、时长、包含金币、购买价格、介绍、上架状态、可用模型/渠道组、并发、队列优先级、保留上限和版本发布。
- 余额账户、账本、人工调整审批。
- 充值订单、支付 provider 配置、回调事件、退款记录。
- 任务队列和重试监控。
### 6.5 系统、存储与审计
- 对象存储、临时结果保留期、WebDAV 策略。
- 结果/原图/manifest 归档、用户延长次数和 GC 执行状态。
- WebSocket 连接、心跳、事件积压和断线重连指标。
- 任务、媒体和日志清理策略。
- 审计日志、管理员操作记录、密钥轮换记录。
- 系统错误、provider 告警和消息 outbox。
## 7. 现有代码迁移规划
### 7.1 前台代码复用
保留并逐步改造:
- `MiragenFlow-front/src/data/artworks.ts`:不进入 V1 运行时;首页不保留演示作品数据,公开模型目录和工作流状态必须来自真实 API。
- `MiragenFlow-front/src/App.tsx`、`src/main.tsx`:不直接复制;重写到 `web/src/app/`,改用项目现有 BrowserRouter、认证守卫、错误边界和统一 providers,不能把 hash 路由作为 V1 公网路由。
- 各页面和组件的 `*.module.css`:随对应组件迁移到目标目录;公共 token 合并到 `web/src/styles/`,不复制一份互相覆盖的全局 CSS。
- `MiragenFlow-front/src/components/primitives/*`:迁移到 `web/src/components/ui/`,保留按钮、输入、反馈、选择器的视觉规范;不把组件验收页作为生产导航。
- `MiragenFlow-front/src/components/layout/*`:迁移到 `web/src/components/layout/`,接入真实登录、余额、通知、账户和权限状态。
- `MiragenFlow-front/src/components/content/*` 与 `src/pages/HomePage.tsx`:视觉原则已吸收至 `web/src/pages/home/`;首页内容、模型目录和任务入口使用真实 API,不复制演示作品流或占位页。
- `MiragenFlow-front/src/styles/*`:合并到 `web/src/styles/`,以现有画布主题、TDesign/Tailwind tokens 为最终来源,避免两套全局变量并存。
- `MiragenFlow-front/src/assets/holopix/*`:迁移到 `web/src/assets/reference/`;只允许作为前台公开素材或视觉参考,禁止在其中放配置、用户上传文件、响应数据或密钥。
- `MiragenFlow-front/src/pages/ComponentsPage.tsx`:迁移为受保护的开发验收入口或移出生产构建,不保留“组件中心”作为普通用户功能。
- `MiragenFlow-front/src/pages/PlaceholderPage.tsx`:只作为迁移过渡,不进入一期生产路由;真实页面完成后删除。
- `MiragenFlow-front/src/components/primitives/primitives.test.tsx`:迁移到 `web/src/components/ui/__tests__/` 或按现有测试结构重写;测试 fixture 不进入生产 bundle。
- `MiragenFlow-front/public/favicon.svg`、`public/icons.svg`:只在完成版权、命名和内容核验后迁移到 `web/public/`;不得把不明 SVG 中的外链、脚本或用户数据带入静态目录。
- `MiragenFlow-front/index.html`:重建为 `web/index.html`,只保留元境幻生标题、favicon 和公开 meta,不复制模板的 `/src/main.tsx` 引用或演示标题。
- `MiragenFlow-front/package.json`、`package-lock.json`、`vite.config.ts`、`tsconfig*.json`、`.oxlintrc.json`:不直接覆盖现有 `web/` 构建配置;按依赖和脚本逐项评估后合并,锁文件只保留 web 自身的一份。
- `MiragenFlow-front/docs/COMPONENTS.md`、`README.md`:迁移到 `docs/design-reference/` 作为设计输入记录,不能当作产品文档或运行时依赖。
- `MiragenFlow-front/dist/`、`node_modules/`、临时截图和构建缓存:不作为源码迁移,不提交仓库;即使目录已存在,也不得复制其中 hashed JS/CSS、图片或字体到生产资源。
- `web/src/pages/canvas/project.tsx`:保留节点交互、画布编排、结果回写和本地编辑工具。
- `web/src/components/canvas/*`:保留节点 UI、裁剪、蒙版、切分、角度和批量结果 UI。
- `web/src/lib/canvas/canvas-node-generation.ts`:改为组装平台任务请求和引用资源。
- `web/src/lib/canvas/canvas-export.ts`、`web/src/services/webdav-sync.ts`:保留用户导出和 WebDAV 能力。
- `web/src/stores/use-asset-store.ts`、`useCanvasStore`:先支持本地恢复,再增加用户/云端任务关联。
### 7.2 必须移出用户端的能力
- `web/src/stores/use-config-store.ts` 中的 Base URL、API Key、供应商渠道管理。
- `web/src/components/layout/channel-editor-drawer.tsx` 的用户渠道编辑。
- `web/src/components/layout/model-script-editor.tsx` 的用户自定义供应商脚本。
- `web/src/services/api/image.ts`、`audio.ts` 中直接携带外部 Key 的浏览器请求。
这些逻辑迁移到服务端 adapter/gateway。前台配置面板改为公开模型档位、分辨率、数量、语言、主题、WebDAV 和账户设置。
### 7.3 后台模板改造
- 保留 TDesign Layout、菜单、主题、表格、表单和结果页组件。
- 删除模板示例业务的 mock 数据、Tencent/tdesign 示例链接、合同/商品示例命名。
- 将页面替换为用户、认证消息、渠道、渠道组、模型产品、任务、余额、充值、支付、审计。
- 统一通过 `/api/v1/admin/*` 调用服务端,不再在页面里写静态演示数据。
### 7.4 同一公网入口
最终对外建议保持一个 origin:
```text
/ 前台静态资源
/admin/ 后台静态资源
/api/ 业务 API、认证、任务、余额
/api/v1/ws/ WebSocket 长任务事件(V1 主通道)
```
开发环境可以继续保留两个 Vite 进程;生产环境由反向代理统一转发,前台和后台不能依赖不同公网端口。
### 7.5 模板接入原则
- `MiragenFlow-front` 是一次性模板输入目录,不作为运行时 package、workspace 或静态资源根目录;迁移完成后删除临时目录,或仅保留到 `docs/design-reference/` 供设计追溯。
- `web/`、`admin/` 和 `server/` 只能通过 `packages/contracts/` 共享 API 类型、错误码和事件 schema;前台不得 import server 文件,server 不得 import web/admin 页面。
- 浏览器端只能保存公开目录、主题、语言和本地画布/资产数据;Access Token 在内存,Refresh Token 使用 HttpOnly Cookie,provider 凭证和 WebDAV 密码只在服务端密文/KMS 中保存。
- `.env.example` 只允许公开地址、功能开关和非敏感默认值;真实 `.env`、密钥、支付签名、短信/邮件凭证和 provider Key 不进入 git、构建产物、`public/`、日志或图示文档。
- 用户上传、任务 staging、WebDAV 下载和导出文件必须使用服务层授权,不得放进 `web/public/`、`admin/public/` 或可被 Vite 静态访问的目录。
- CI/提交前检查必须拒绝 `*.env`、`*.pem`、`*.key`、上传目录、staging 目录、数据库快照和疑似 Authorization/API Key 内容;构建产物扫描通过后才能发布前台或后台静态资源。
## 8. 一期验收标准
### 8.1 用户链路
- 普通用户默认使用邮箱或手机号加密码直接注册并登录;后台开启验证策略后,才需要邮箱/短信验证、人机校验或 MFA。
- 用户可以登录、刷新、退出、重置密码,冻结账户不能提交任务。
- 登录后能看到公开模型产品、分辨率、数量、预计余额消耗。
- 前台网络请求中不出现 provider API Key、Base URL、provider model ID 或渠道顺序。
- 用户可以提交图片、文本、音频和已纳入的图片工具任务。
- 任务支持排队、进度、取消、结果、失败重试和历史查询。
- 长任务通过 WebSocket 接收心跳、进度、attempt 和终态事件;断线后可使用 cursor 重放,轮询只作为降级。
### 8.2 路由和计费
- 一个分组有四个渠道时,第一渠道失败会自动继续第二、第三、第四渠道。
- 单渠道重试不会创建新的用户扣费。
- 全组不可用时任务给出公共错误和同档位切换建议。
- 余额不足不能入队;任务成功只扣实际成功结果。
- 全失败、取消和系统错误会释放预扣余额。
- 重复幂等请求不会重复创建任务或扣款。
- 支付回调重复到达不会重复增加余额。
- 金币单位、图标/文字、换算比例和套餐版本修改不影响历史订单和已创建任务快照。
- 任务创建后修改模型价格或渠道 priority,不改变该任务的快照、路由和用户价格。
- provider 已接受但网关超时会进入 `unknown` 对账流程,不直接重复生成;worker 崩溃可由 lease 恢复且不重复结算。
- reserve/settle/release/refund 任一重复事件都保持账本不变量,过期预扣能被 reconciler 找回。
### 8.3 管理后台
- 管理员能配置渠道、渠道组、priority、内部模型 ID、模型产品、分辨率和价格。
- 管理员能配置金币单位、换算比例、套餐名称/时长/价格/金币/介绍/上架状态、可用模型或渠道组、并发和队列优先级。
- 管理员能看到健康、失败 attempt、任务状态、余额账本、充值订单和消息 outbox。
- 管理员写操作有权限校验和审计记录。
- 不同角色无法读取越权用户对象、完整提示词、WebDAV 凭证或渠道密钥;高风险操作需要重新认证/审批。
- 禁用一个渠道后,路由自动跳过;恢复后按策略重新参与。
- 后台不展示明文 Key,日志不记录完整敏感请求和响应。
### 8.4 前台能力
- 画布现有节点、连线、导入导出、WebDAV 和本地图片工具不因网关迁移而回归。
- 基础/高级/旗舰和分辨率选项由后台目录动态控制。
- 游戏资产、艺术资产、参考图、反推提示词、多角度、局部编辑、抠图、拆分、放大具备统一任务状态和结果回写;3D 入口在 V1 不发布,调用预留契约返回 `CAPABILITY_NOT_ENABLED`。
- 参考图/mask 只能引用当前用户已上传且通过扫描的对象;结果签名 URL 按用户/任务/输出授权并可过期或撤销。
- 视频/动画入口不存在,避免把未开发功能暴露给用户。
- 3D 生成入口不存在;调用预留 3D 契约返回 `CAPABILITY_NOT_ENABLED`。
- V1 不包含模型训练和内容治理;内容治理需求进入 V2 规划。
## 9. 当前阶段明确不开发
- 视频生成、首尾帧、图生视频、文生视频。
- 动画时间轴、骨骼、动效编辑器和视频序列导出。
- Local Agent、Codex、MCP、Skill、远程 Prompt 和远程插件市场。
- 面向用户的供应商 API Key、Base URL、原始 model ID 和自定义调用脚本。
- 多人实时协作、团队空间和公开模型市场;V1 不实现,但保留 organization/team、成员邀请、workspace owner、共享资产、团队余额和对象范围字段/接口预留。
- 内容治理不进入 V1;敏感词、图片审核、版权标记、投诉处理和人工复核统一列入 V2。
- V2 内容治理预留:`moderation_policies`、`moderation_decisions`、`copyright_marks`、`complaints`、`manual_reviews`;V1 只保留 provider 拒绝结果和基础文件扫描,不建设治理后台流程。
版本边界:
| 版本 | 纳入范围 |
| --- | --- |
| V1 | 认证/防刷/两步验证、金币余额和换算、人工/mock 充值、套餐、异步队列、WebSocket、本地 + WebDAV、图片/音频/2D 多视图工具、渠道路由和后台管理 |
| V2 | 内容治理、敏感词/图片审核、版权标记、投诉和人工复核 |
| 后续 | 真正图生 3D/文生 3D、团队协作、模型训练、对象存储正式启用、公开模型市场、视频/动画 |
## 10. 一期交付顺序和依赖
按以下顺序拆分开发,前一阶段的契约和数据约束作为后一阶段的输入:
1. **基础工程与安全底座**:服务端项目、数据库迁移、配置/密钥管理、统一错误码、requestId、用户/管理员认证、RBAC、审计和限流。
2. **余额与消息底座**:余额账户和账本状态机、预扣/结算/释放、充值订单与支付 adapter 接口、邮件/SMS outbox、验证码策略和对账任务。
3. **模型目录与渠道路由**:渠道、渠道组、模型产品、分辨率/价格发布版本、健康探活、熔断、attempt 状态机、队列 lease、未知结果对账。
4. **任务网关**:上传对象、图片/文本/音频 adapter、统一任务 API、WebSocket 长任务进度、HTTP 轮询降级、取消/重试、签名结果 URL和输出持久化。
5. **前台账户和目录改造**:登录注册、账户/余额/账单、公开模型目录、配置面板替换为产品选项,移除浏览器 provider Key/脚本入口。
6. **画布接入平台任务**:保留节点和交互,改写生成上下文、引用对象、进度、结果回写、取消和错误提示;保留本地导入导出与 WebDAV。
7. **游戏/艺术资产工具**:反推提示词、多角度、局部编辑、抠图、规则切分/全能拆分、放大、扩图等统一接入任务能力矩阵。
8. **套餐与后台业务页面**:完成 TDesign 后台的用户、认证、渠道、模型、套餐、任务、余额、支付、存储、审计页面;3D 仅保留禁用的 adapter 契约和 feature flag,不纳入 V1 交付。
9. **联调与验收**:按第 8 节逐项验收,覆盖故障切换、重复事件、余额不变量、权限越权、WebDAV 冲突和前台无 provider 凭证。
视频、动画时间轴、团队协作实现、公开模型市场、模型训练和 V2 内容治理不阻塞前述一期主链路。
## 11. 目录结构和模板接入树
一期统一采用以下目录边界。目录名称先固定,后续实现不得把服务端密钥、用户文件或 provider 请求代码放入前台/后台静态目录。
### 11.1 当前模板输入快照
当前提供的模板目录为 `/Users/qiu/Desktop/MiragenFlow/docs/design-reference/MiragenFlow-front`,其用途是用户端视觉和交互基础,不是新的独立产品目录:
- 技术栈:Vite 8、React 19、TypeScript、React Router 7、Zustand、TanStack Query、Lucide React、CSS Modules。
- 当前入口:`src/main.tsx` -> `src/App.tsx` -> `AppShell`;使用 hash 路由,已有 `home`、`components`、`models`、`create`、`canvas`、`assets` 六个演示路由。
- 已有视觉基础:`src/components/primitives/` 基础组件、`src/components/layout/` 壳层、`src/components/content/` 首页内容、`src/styles/` tokens/global、`src/assets/holopix/` 公开参考素材;其中 `alimama.woff2` 被 tokens 引用,迁移前必须完成字体版权和静态资源核验。
- `ComponentsPage` 是设计系统验收页,`PlaceholderPage` 是模块占位页;二者不能作为 V1 用户业务页面或默认导航。
- 当前模板没有真实认证、模型目录、余额、任务 API、WebSocket、WebDAV 服务端或 provider 调用;接入时必须迁移到本项目 `web/` 并替换 mock/占位逻辑。
- `dist/` 和 `node_modules/` 属于构建产物/依赖缓存,禁止迁入源码、Docker 镜像或生产静态目录。
```text
MiragenFlow/
├── web/ # 用户端,唯一面向普通用户的前台应用
│ ├── public/ # 仅公开 favicon、静态图标和无敏感信息资源
│ └── src/
│ ├── app/ # AppProviders、路由、权限守卫、错误边界
│ ├── pages/ # home、auth、workspace、canvas、tools、tasks、assets、account、settings
│ ├── components/
│ │ ├── ui/ # MiragenFlow-front primitives 迁移后的基础组件
│ │ ├── layout/ # Header、Sidebar、UserMenu、NotificationCenter
│ │ ├── home/ # Hero、作品卡片、发现和筛选
│ │ ├── generation/ # Prompt、ModelPicker、Queue、Result
│ │ ├── canvas/ # 画布节点、工具栏、属性面板和导出
│ │ ├── assets/ # 资产卡片、上传队列、详情抽屉
│ │ ├── account/ # 余额、套餐、账单、会话
│ │ └── storage/ # WebDAV、同步、归档和保留状态
│ ├── services/
│ │ ├── api/ # 只调用 /api/v1,不保存 provider 地址或 Key
│ │ ├── realtime/ # WebSocket 连接、心跳、cursor、任务事件去重
│ │ └── storage/ # localforage/IndexedDB、ZIP、WebDAV 客户端
│ ├── stores/ # auth、catalog、balance、tasks、canvas、assets、settings
│ ├── hooks/ # 跨页面复用的 UI 副作用和任务订阅
│ ├── lib/ # 纯函数、校验、错误码、格式化和画布工具
│ ├── styles/ # tokens、global、主题和第三方覆盖
│ └── types/ # 前台类型,公共 API 类型从 packages/contracts 引入
├── admin/ # TDesign 管理台,不承载用户端页面
│ ├── public/ # 仅公开静态资源
│ └── src/
│ ├── pages/ # dashboard、users、auth-messages、channels、groups、products、plans、tasks、billing、storage、audit
│ ├── router/ # /admin 路由和权限元数据
│ ├── services/ # 只调用 /api/v1/admin/*
│ ├── stores/ # admin session、RBAC、filters、dashboard metrics
│ ├── components/ # 管理台私有表格、表单、审批和时间线
│ └── styles/ # 管理台主题和 TDesign token
├── server/ # 一期新增的服务端网关和任务系统
│ ├── src/
│ │ ├── app/ # HTTP/WS bootstrap、middleware、error boundary
│ │ ├── modules/ # auth、admin-auth、users、catalog、billing、plans、channels、tasks、providers、messages、storage、webdav、audit
│ │ ├── adapters/ # provider、payment、email、sms、staging、future object storage
│ │ ├── infra/ # PostgreSQL、Redis、queue、WS broker、KMS、observability
│ │ ├── jobs/ # retry、unknown reconciliation、outbox、GC、archive、payment reconciliation
│ │ └── shared/ # domain errors、idempotency、requestId、security helpers
│ ├── migrations/ # 数据库迁移,禁止把密钥或生产数据提交进来
│ └── tests/ # 单元、集成、路由故障、账本和权限测试
├── packages/
│ └── contracts/ # API DTO、WS event schema、错误码、能力矩阵和版本常量
├── docs/ # 用户文档、开发文档和图示
├── scripts/ # dev/build/迁移/校验脚本
├── assets/ # 仓库级公开素材,不放用户上传或服务端响应
├── docs/design-reference/ # 临时模板输入和视觉参考,不参与运行时构建
└── .env.example # 只放公开配置示例,不放任何真实凭证
```
模板迁移映射固定如下:
| 临时模板路径 | 目标路径 | 处理方式 |
| --- | --- | --- |
| `src/components/primitives/` | `web/src/components/ui/` | 合并基础组件,保留交互状态和可访问性 |
| `src/components/primitives/primitives.test.tsx` | `web/src/components/ui/__tests__/` | 迁移或重写测试,不进入生产 bundle |
| `src/components/layout/` | `web/src/components/layout/` | 接入真实会话、余额、通知和权限 |
| `src/components/content/` | `web/src/pages/home/` | 仅吸收视觉原则,首页使用真实 API |
| `src/data/artworks.ts` | 不迁移 | 删除演示数据,生产改接公开 API |
| `src/App.tsx`、`src/main.tsx` | `web/src/app/` | 重写入口、providers、BrowserRouter 和守卫,不复制 hash 路由 |
| `src/pages/HomePage.tsx` | `web/src/pages/home/index.tsx` | 改为真实首页和公开目录入口 |
| `src/pages/*.module.css` | 对应 `web/src/pages/*` | 随页面迁移,合并 tokens |
| `src/pages/ComponentsPage.tsx` | `web/src/pages/dev/components/` | 仅开发验收使用,不进普通用户导航 |
| `src/pages/PlaceholderPage.tsx` | 不迁移 | 真实页面完成后删除 |
| `src/assets/holopix/` | `web/src/assets/reference/` | 只放公开设计素材,不放业务数据 |
| `public/favicon.svg`、`public/icons.svg` | `web/public/` | 版权、脚本和外链核验后迁移 |
| `index.html` | `web/index.html` | 重建标题、favicon 和公开 meta |
| `package.json`、`package-lock.json`、Vite/TS/Oxlint 配置 | 不直接复制 | 逐项合并到 web 构建配置 |
| `README.md`、`docs/COMPONENTS.md` | `docs/design-reference/` | 仅作设计输入记录 |
| `dist/`、`node_modules/` | 不迁移 | 构建产物和依赖缓存禁止作为源码 |
## 12. 系统图示
页面结构、ASCII(SSI)图示、用户侧逻辑、管理员侧逻辑、系统请求时序、整体架构和数据关系统一维护在 [system-diagrams.md](system-diagrams.md)。
该文档覆盖当前已有页面和一期规划页面,并明确标记 `current`、`phase 1` 与“待确认”范围。新增页面、API、任务状态或账本状态时,必须同步更新图示文档,避免页面规划与调用链脱节。
## 13. 已确认决策和实现参数
本期范围已经收敛,不再把以下内容列为待确认功能:
- 不接第三方登录;用户邮箱/短信验证、验证码防刷和用户两步验证作为可配置增强能力,普通用户默认关闭;管理员 MFA/人机验证码同样默认关闭,并支持审计启用/关闭。
- V1 统一余额单位默认称为“金币”,支持后台配置文字/图标、换算比例、舍入和版本;不使用“积分”作为用户界面概念。
- 充值只做管理员人工充值、mock provider 和支付接口预留;真实支付等用户提供第三方文档后接入。
- 所有长任务使用异步队列,WebSocket 为进度主通道,HTTP 轮询为降级;V1 不做 SSE 主通道。
- V1 使用浏览器本地 + WebDAV,平台对象存储只保留 adapter 接口且默认关闭;保留、归档、用户延长次数由后台可视化配置。
- V1 不开放真正图生 3D/文生 3D、模型训练或内容治理;3D 仅保留契约和 feature flag,内容治理列入 V2。
- V1 每日任务数不设上限,但必须限制并发、队列优先级、套餐权益、单文件大小和结果保留策略。
- V1 不做团队协作,但预留 organization/team、成员、workspace owner、共享资产、团队余额和对象授权字段/接口。
仍需在实现阶段确定的只是参数和供应商细节,不改变上述范围:
1. 图形验证码、人机挑战和风控供应商的具体选型、阈值和地区策略。
2. 管理员 IP 白名单、硬件密钥等增强策略是否在默认 MFA 之外启用。
3. 真实支付 provider、回调字段、签名算法和对账周期,等待第三方支付文档。
4. 任务结果、原图和 WebDAV manifest 的默认 TTL 数值、归档目录格式、用户延长的具体上限。
5. 退款/拒付 provider 流程的字段映射;平台内部 release、refund 和人工调账状态机不改变。