Files
digital-me-history/digital-me-backend/DEPLOY-CHECKLIST.md
T
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

83 lines
5.0 KiB
Markdown
Raw 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.
# 数字我 / Digital Me — 生产环境配置 Checklist
> 逐项对照 `digital-me-backend/.env`。分四档:🔴 不设=有洞/起不来 · 🟠 强烈建议 · 🟡 按功能可选 · ⚪ 可留默认。
---
## 🔴 0. 总开关(漏了这个,前面所有安全修复都白做)
- [ ] **`NODE_ENV=production`**
这是本次安全修复的**总开关**。不设它(默认 development)会导致:
- 忘记密码 / 短信验证码 **明文回传**(任意账户可被接管)
- 商店 stub 通道 **免支付开通 + 冒充登录**
- 微信 `mock-scan` 后门 **开着**
- `assertProdConfig` 直接跳过 → **默认 JWT 密钥都不会被拦**
> 部署后务必确认进程真的读到了 `production`:启动日志应是 `on :3701 (production)`。
## 🔴 1. 起不来 / 必设
- [ ] **`JWT_SECRET`** = 强随机值(≠ `change-me-in-prod`)。生产下不设,服务**拒绝启动**(fail-fast,符合预期)。
生成:`openssl rand -hex 32` 或 `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
- [ ] **`MONGO_URI`** = 你的生产 Mongo(默认 `mongodb://localhost:27017` 仅本机可用)。
- [ ] **`MONGO_DB`** = `digital_me`(独立库,别和别的产品共用)。
- [ ] **`CORS_ORIGINS`** = 前端真实域名(如 `https://digitalme.invoratec.cn`)。不对会导致前端跨域被拦。
- [ ] **`PUBLIC_URL`** = 本 API 的公网地址(如 `https://digitalme-api.invoratec.cn`)。捏脸/口播视频靠它被 DashScope 回拉素材,必须公网可达。
## 🟠 2. 强烈建议(安全 / 生产质量)
- [ ] **`DATA_ENC_KEY`** = 任意强随机串。不设 → 访客聊天记录**明文入库**(`assertProdConfig` 只 warn 不拦)。
- [ ] **`SUPER_ADMIN_EMAILS`** = 你的邮箱(逗号分隔)。不设 → 没人能授予蓝V认证 / 进后台。
- [ ] **`TRUST_PROXY`** = 生产默认自动 on;若**不在** nginx/cloudflare 后面才需显式 `false`(否则限流按错 IP)。
- [ ] **`MAX_QUESTION_LEN`** = 默认 2000,按成本/滥用容忍度调。
- [ ] **`MODERATION_MODE` / `MODERATION_URL`**:默认只有内置正则兜底。接专业内容安全服务(`MODERATION_URL`)或 `MODERATION_MODE=llm` 更稳(live 视频对话现在也走审核了)。
## 🟡 3. 按功能可选(不配=优雅降级,不会崩)
| 功能 | 需要的 env | 不配的表现 |
|---|---|---|
| AI 聊天 / 知识 RAG | `DASHSCOPE_API_KEY` | 聊天 → 502;其余正常 |
| Claude 兜底 | `ANTHROPIC_API_KEY` | Qwen 挂了没有兜底 |
| 捏脸(万相) | `AVATAR_PROVIDER=dashscope` + 公网 `PUBLIC_URL` | 用上传原图(往往更像本人,OK) |
| 声音克隆 / TTS | `DASHSCOPE_API_KEY` | `voice-not-cloned` |
| 口播视频(EMO) | `DASHSCOPE_API_KEY` + 公网 `PUBLIC_URL` | 不可用 |
| 英文原生发音 | `AZURE_SPEECH_KEY` | 回退克隆音色/浏览器 TTS |
| 手机短信登录 | `SMS_PROVIDER=aliyun` + `ALIYUN_SMS_*` | 生产下**直接不可用**(已 fail-closed,不再泄露验证码)※ |
| 邮箱找回密码 | `EMAIL_PROVIDER=<非stub>` + 实现 `sendEmail` | 生产下**直接不可用**(已 fail-closed)※ |
| 微信扫码登录 | `WECHAT_APP_ID` + `WECHAT_APP_SECRET` | stub 二维码在生产被关,等于登录方式不可用 |
| 商店真实收款 | `STORE_PROVIDER=wechat` + `WXPAY_*` 全套 | 生产下 stub 返回 `payment-unavailable`(不再白嫖)|
| 媒体持久存储 | `OSS_*` 四要素(region 带 `oss-` 前缀)| 回落本地磁盘,重部署会丢片 |
| 分享卡富预览 | `SPA_INDEX_PATH`(+ Nginx 回源)| 回落 meta+跳转壳 |
| 公众号转发卡 | `WX_MP_APP_ID/SECRET`(+ JS 安全域名)| 前端休眠 no-op |
| 钱包/付费咨询栈 | `FEATURE_MARKETPLACE=true` | 默认关闭(定位「不做平台」)|
> ※ 短信/邮箱登录:这是本次安全修复的**有意行为** —— 生产没配真实 provider 就不可用,总比"回传验证码给任何人"强。要启用就配真 provider;不打算用就保证注册/登录还有邮箱密码这条路。
## ⚪ 4. 可留默认
`PORT` `EDITION=both` `JWT_EXPIRES=7d` `LLM_MODEL` `EMBED_MODEL` `AVATAR_STYLE` `TOKENS_PER_YUAN` 等。
---
## ✅ 部署后自检(3 条)
```bash
# 1) 确认进程真在 production 模式
# 启动日志应含: on :3701 (production)
# 2) 生产必须 fail-closed:忘记密码不返回验证码(响应里不应出现 devCode)
curl -s -X POST https://<api域名>/api/auth/password/forgot \
-H 'content-type: application/json' -d '{"email":"someone@x.com"}'
# 期望:{"sent":true}(无 devCode)或 502;绝不能出现 devCode 字段
# 3) 微信 mock-scan 后门必须已关(应 404)
curl -s -o /dev/null -w "%{http_code}\n" https://<api域名>/api/auth/wechat/mock-scan/anystate
# 期望:404
```
---
## ⚠️ 一次性 / 数据层
- 新增集合 `plaza_ratings` + 唯一索引 `{slug,voter}`:首次启动 `connectDb()` **自动建**,无需手动迁移。
- 未改任何既有字段(`isPublic` 等原样),无数据迁移风险。