# 安全、内容合规、部署与运维 ## 1. 安全目标 保护用户私有故事与素材、平台聚合站凭据、钱包资金和执行身份。把面向公众 SaaS 与个人本地工具区分开:不能依赖“只有自己使用”“后台只有管理员”或“文件名不可猜”作为安全措施。 ## 2. 身份和权限 - 使用成熟身份组件或受审查实现;密码采用强密码哈希,登录与邮箱验证码有频率、设备和风险限制。 - 管理员启用 MFA,修改凭据、退款与权限授权需要近期认证;首个管理员通过一次性受控 bootstrap 创建,不预置账号密码。 - cookie 使用 HttpOnly/Secure/SameSite,写请求验证 CSRF/Origin;配置 CSP、防点击劫持与安全响应头。 - 关键资源按工作区归属与复合引用校验;查询、导出、任务、SSE、对象签名和后台操作全部覆盖。 - 普通客服默认不能阅读用户素材;临时支持授权有范围、期限与审计。 ## 3. 凭据与敏感配置 平台 key 采用信封加密或 AES-GCM,主密钥放部署 Secret/KMS,不在数据库、仓库或镜像中。定期轮换、撤销并验证旧任务恢复策略。读 API 不返回密钥明文或密文;日志、错误、trace、支付元数据和生图记录都按白名单记录。 本轮 `/workspace/ai-image/index.js` 的凭据只用于用户批准的文档生图,**不成为新平台默认配置**。其地址与凭据未写入本设计文档。后续正式产品接入必须重新由管理员在后台完成。 ## 4. 出站网络与 SSRF 主要攻击面不只 Base URL,还包括上游返回的结果 URL、重定向、上传回调、媒体参考链接和代理配置。 1. 默认只允许 HTTPS 与已批准端口,不允许 URL 凭据、任意 scheme 或 file/data/gopher 旁路。 2. 检查 DNS 的所有结果与实际连接地址,拒绝回环、私网、链路本地、云元数据和保留地址;不能只检查字符串中的 hostname。 3. 每次重定向重新验证;跨 origin 不转发 Authorization、cookie 或平台 key。 4. DNS rebinding 需在实际 socket lookup/连接策略中防护,不是“先解析一次然后普通 fetch”就完成。 5. 自建私网 New API 只有运维配置的精确出站白名单例外;后台用户不能绕过这层。元数据目标始终禁止。 6. 限制下载大小、超时、压缩解包、跳转次数与并发;流式读取也计数,避免无 Content-Length 绕过。 7. 生成平台的运行环境不默认安装或依赖 Mihomo;代理仅是运维明确配置的受控出口。当前工作环境使用代理不代表产品自动修改宿主网络。 ## 5. 文件与媒体处理 上传 MIME、扩展名、尺寸、时长均不可信,使用实际解码与探测验证。FFmpeg/FFprobe 运行于受限容器/用户,限制 CPU、内存、磁盘、进程和网络;任务目录不可执行,禁止 shell 拼接与用户任意滤镜表达式。 浏览器内联显示只接受审查后的安全类型;用户 SVG/HTML 等可能含脚本的内容不以同源可执行资源渲染。对象存储 key 随机且由服务端分配,路径与文件名规范化,禁止目录穿越和符号链接逃逸。 原始素材、预览代理与正式成片分开生命周期;公开分享是明确授权功能,不是生成时默认公开。对象权限与签名 URL 均有撤销/过期策略。 七牛云存储沿用用户已配置的空间、地域、域名和前缀,不因 `QINIU_PUBLIC_DOMAIN` 的名称将空间改为公开。上线验收需验证私有空间及实际下载域名的访问控制;若经 CDN 分发,同时检查缓存、CDN 鉴权与源站是否存在无签名旁路。无法保护的公开链路不用于私有素材。浏览器上传凭证绑定指定空间、对象 key、期限和上传限制;CORS 仅允许实际应用来源,CORS 本身不是素材访问权限。 ## 6. 内容与权利 - 发布前确定首发地区、数据驻留、内容审核、生成式内容标识、服务条款与供应商要求,咨询适用专业意见。 - 输入故事、图片、声音和音乐需用户声明权利;提供举报、下架、申诉和权利撤回渠道。 - 拒绝非法、剥削未成年人、未经同意的性化深度伪造等内容;上游拒绝不能通过换渠道规避。 - 真人音色和肖像默认保守处理,声纹/克隆功能单独评估同意、证据与撤销。 - 对外生成内容标识、水印/元数据、标识保留和导出规则根据运营地区确定,不声称加一个提示就满足所有法律要求。 - 不能通过完全公开素材桶做内容审核;审核访问最小化、留审计,避免二次泄漏。 ## 7. Agent 的权限边界 用户文本、小说、上游响应都可能包含提示注入。创作助手只得到当前任务所需上下文和受控业务工具,不能读取平台凭据、任意文件、跨租户资源或 shell。工具能力不等于消费授权;每次付费必须有匹配 Grant。项目文字不能修改系统权限、价格或后台配置。 首版不开放任意代码/第三方脚本供应商,不把 Node VM 视为强安全边界。未来插件需要隔离进程、出站限制、租户隔离和签名发布审查。 ## 8. 建议部署拓扑 | 服务 | 初期部署建议 | 扩展方向 | | --- | --- | --- | | Web / API | 独立 Node.js 进程,可在同一受控节点起步;API 由 PM2 管理 | API 无状态横向扩展,是否增加实例先验证业务并发边界 | | Submit / Poll / Ingest | 按任务类型独立进程,可共享镜像 | 按渠道、模态和延迟扩池 | | Render | 单独资源池与临时卷 | CPU 与 I/O 独立扩展,不需推理 GPU | | PostgreSQL | 托管优先,自动备份与 PITR | 先优化索引/连接池再评估读副本 | | Redis | 独立实例、持久化、ACL | 高可用与调度恢复演练 | | 七牛云 Kodo | 复用已配置的空间、地域、访问域名与 key 前缀;私有素材受控访问 | 按素材保留策略配置生命周期,CDN 只分发受控预览与授权内容 | | Secret / KMS | 独立密钥管理 | 主密钥轮换与审计 | 本轮不执行 Docker Compose、不开放端口、不安装基础设施。部署步骤是未来实施建议。线上不把数据库或 Redis 端口暴露到公网,不使用示例密码。 后续基础工程已提供 `ecosystem.config.cjs`:PM2 仅管理 `kumo-drama-api`,使用单进程 fork、生产环境、自动重启与有界退出窗口;Nest 启用 shutdown hooks。默认监听本机 `127.0.0.1:3200`,公开 TLS 入口交给受控反向代理。不自动执行全局 PM2 清理、`save`、系统启动注册或服务重启;生产以专用非 root 用户运行。PM2 不是数据库、队列或付费任务恢复方案。 ## 9. 配置边界 环境只保存基础设施与运维配置,例如数据库 DSN、Redis、存储、会话签名、加密主密钥引用、允许的出站策略。业务 AI 连接来自管理员数据库发布版本,禁止同时有 `.env`、源码常量和数据库三套权威来源。 基础工程通过 `NODE_ENV` 区分 `apps/api/.env.development` 与 `apps/api/.env.production`:开发命令固定使用前者,生产命令及 PM2 固定使用后者;测试不加载环境文件。API 与 Prisma CLI 共享文件选择规则,不回退到通用 `.env` 或另一环境文件,部署进程环境变量优先。真实环境文件均不提交,只保留对应 `.example` 模板;已有开发配置不得自动复制为生产凭据。 配置有结构校验,Secret 缺失时相关服务 fail closed。新安装无 AI 连接是合法产品状态,不应导致整个平台连登录和配置页都无法启动。 ### 七牛云 Kodo 环境变量 存储选型已确认,用户已准备好以下六项配置。它们属于**基础设施配置**,由部署环境或 Secret 注入 API 与相关 Worker,不通过 AI 渠道后台维护;不要求重新提供或复制真实密钥到文档。本轮仅记录配置契约,未检查实际值、空间权限、域名连通性或上传下载结果。 | 环境变量 | 用途 | 约束 | | --- | --- | --- | | `QINIU_ACCESS_KEY` | 七牛访问凭据 AK,用于服务端签发上传/下载凭证及管理请求 | 不作为独立字段或客户端配置下发,不写入仓库、日志或文档 | | `QINIU_SECRET_KEY` | 七牛签名密钥 SK | 仅服务端 Secret 使用,不进入浏览器、响应、日志或镜像 | | `QINIU_BUCKET` | 本项目使用的七牛存储空间名称 | 与 AK/SK 授权及实际空间一致;客户端不能覆盖目标空间 | | `QINIU_PUBLIC_DOMAIN` | 已绑定的文件访问域名或 CDN 基础地址 | 规范化为 HTTPS 地址;不得含账号密码、签名或临时查询参数;不等于允许匿名读取私有素材 | | `QINIU_REGION` | 空间所在地域,驱动 SDK 地域与上传节点选择 | 使用当前 SDK 支持且与空间一致的地域标识;未知值明确报错,不猜测或回退其他地域 | | `QINIU_KEY_PREFIX` | 本应用对象 key 的统一前缀 | 规范化为相对前缀,禁止路径穿越;可显式为空,但仍追加工作区与随机对象身份 | 前五项必须配置且非空,`QINIU_KEY_PREFIX` 必须显式声明,可为空。API 与 Worker 使用一致的目标空间、地域和前缀规则;不得将这些变量设为 `NEXT_PUBLIC_*` 或打包进前端。`QINIU_PUBLIC_DOMAIN` 可出现在经授权签发的文件链接中,属于访问入口而非凭据。Qiniu AK/SK 与 AI 渠道密钥是不同凭据:存储使用环境配置不改变“AI 渠道数据库初始零地址、零密钥”的要求。 配置缺失或非法时,依赖存储的上传、转存和导出入口不可用,不临时改存公开空间或本地目录;保留登录、管理员诊断等不依赖文件存储的能力。七牛上传 token、私有下载 token 及完整签名 URL 按敏感值处理,不持久化为业务身份或写入普通日志。更改空间、域名或前缀前检查历史对象解析与访问策略,不把历史资产重新定位到新空间或新前缀。 ## 10. 可观测性与告警 | 指标/事件 | 用途 | | --- | --- | | requestId / executionId / taskId / attemptId | 串起用户操作与上游事实,不携带 key | | 队列等待与最长年龄 | 发现容量、限流和调度停滞 | | 按渠道/能力的提交、查询、完成与拒绝率 | 区分真正服务故障与用户内容问题 | | outcomeUnknown 与待核对时长 | 防止重复生成和冻结长期占用 | | Ingest 失败、源 URL 即将过期 | 防止付费结果无法交付 | | settlementPending、账本差异、支付未发放 | 资金异常优先处理 | | 预留超期、异常高用量、渠道预算阈值 | 财务与反滥用 | | API 失败率、Worker 心跳、DB 连接与慢查询 | 基础可靠性 | 日常日志只存摘要,不全量记录小说、对白、个人音频、响应体与签名 URL。诊断样本有单独权限、过期与脱敏策略。 ## 11. SLO 与容量:只能先设目标,再实测 建议初始目标:普通非生成 API 的服务端 P95 小于 500ms(不含外部服务);生成接受请求快速返回排队身份;核心业务月度可用性目标 99.5% 起评估。**这些是拟定目标,不是实测指标或对外 SLA。** 上游生成时长单独统计,不能将其算成 Web API 处理能力。 假设 100 个同时在线创作者、20 个远程在途任务、2 个 1080p 渲染作为第一轮压测场景;资源可从业务节点 4~8 vCPU/8~16GB、独立渲染节点 8 vCPU/16GB 级别评估。该配置仅为容量实验起点,正式采购需按码率、片长、候选数、带宽和真实测试调整。 对每用户、工作区、渠道和模态分别设限。不能让一个批次占满所有查询/渲染容量;未知副作用的渠道槽位也不能轻易回收后再发新任务。 ## 12. 备份、恢复和发布 - PostgreSQL 持续备份,定期真实恢复演练;建议内部初始目标 RPO≤15 分钟、RTO≤4 小时,需预算与验证后才能承诺。 - 对象存储和加密密钥独立保护;只有 DB 备份而没有资产或主密钥,不算完整恢复。 - 保护 Outbox、执行 fence、外部 ID、财务账本与配置版本;恢复旧备份后先保护模式核对付费窗口。 - 发布先迁移兼容结构,再部署 API/Worker;长任务优雅停接新提交,已受理任务交接检查点。 - 回滚不能删除已用价格、渠道版本或新的财务记录;不兼容数据库变更优先前向修复。 - Redis 故障后从 DB 重投调度,不重置外部提交身份。 ## 13. 事件响应流程 | 事件 | 首要处置 | 不能做 | | --- | --- | --- | | 渠道 key 泄漏 | 撤销、停止新提交、列出受影响任务、轮换与审计 | 把新 key 写回历史配置伪装未变 | | 生成重复收费疑似 | 停止相关新提交,保留证据与账本,核对上游 | 全部任务 reset 后重跑 | | 支付重复发放 | 冻结风险账户的新消费、核对资金与订单 | 删除历史流水掩盖差异 | | 私有素材泄漏 | 撤销访问、隔离、范围分析、依法通知 | 继续公开分享或删除所有审计 | | 结果转存大量失败 | 恢复同一结果下载、保留远程 ID | 批量重新生成 | | 数据库故障 | 停止付费创建,保护资金与执行身份 | 允许 Redis 离线独立扣费 | ## 14. 上线前安全门禁 权限矩阵与跨租户访问、密钥只写不读、出站 SSRF/DNS/重定向、上传解码、支付验签、账本并发、Agent 工具授权、Worker 双领取、备份恢复、日志脱敏、依赖许可与漏洞扫描必须有明确负责人和可复现验收证据。页面好看或构建通过不能替代这些验证。