# 服务器 Agent 部署交接单

目标：在服务器上把 `bigdata.dtacloud.cn` 跑成可 QA 的生产候选环境。服务器 Agent 按本文执行部署，再按 `docs/PRODUCTION_QA_AGENT_CHECKLIST.md` 做全量验收。

## 交付物

- 源码：必须包含当前工作区全部生产化改动，不要只拉旧 main 分支或旧压缩包。
- 生产环境样例：`.env.production.example`。
- Compose 编排：`docker-compose.yml`、`backend/Dockerfile`、`web/Dockerfile`、`deploy/Caddyfile`。
- 运维文档：`docs/PRODUCTION_RUNBOOK.md`、`docs/BACKUP_RESTORE.md`、`docs/PRODUCTION_QA_AGENT_CHECKLIST.md`。
- 小程序上传包：由开发机生成到 `qa-artifacts/dlbdi-miniapp-weapp-prod-*.zip`，微信开发者工具使用说明见 `docs/MINIAPP_UPLOAD_HANDOFF.md`。

## 部署前必须确认

- 域名 `bigdata.dtacloud.cn` 已解析到服务器公网 IP。
- 服务器外层 nginx 负责开放公网 80/443，Docker 和 Docker Compose 可用；本项目 Caddy 只绑定 `127.0.0.1:8082`。
- 当前代码已经通过发布分组提交或以完整工作区方式同步到服务器；不要只同步旧 main 分支。
- `.env.production` 只在服务器生成，不提交 Git。
- 微信支付证书和公钥只放服务器 `secrets/wechatpay/` 或服务器 Secret，不放仓库。

## `.env.production` 必填项

从 `.env.production.example` 复制：

```bash
cp .env.production.example .env.production
```

必须填真实值：

- `ACME_EMAIL`
- `POSTGRES_PASSWORD`
- `JWT_SECRET`
- `MINIO_ROOT_PASSWORD`
- `S3_SECRET_ACCESS_KEY`
- `ALIBABA_CLOUD_ACCESS_KEY_ID`
- `ALIBABA_CLOUD_ACCESS_KEY_SECRET`
- `ALIBABA_CLOUD_SMS_SIGN_NAME`
- `ALIBABA_CLOUD_SMS_TEMPLATE_CODE`
- `WECHAT_MINIAPP_APP_ID`
- `WECHAT_MINIAPP_APP_SECRET`
- `WECHAT_PAY_MCH_ID`
- `WECHAT_PAY_APP_ID`
- `WECHAT_PAY_API_V3_KEY`
- `WECHAT_PAY_MCH_SERIAL_NO`
- `WECHAT_PAY_PUBLIC_KEY_ID`
- `WECHAT_PAY_PRIVATE_KEY_PATH` 或 `WECHAT_PAY_PRIVATE_KEY_BASE64`
- `WECHAT_PAY_PUBLIC_KEY_PATH` 或 `WECHAT_PAY_PUBLIC_KEY_BASE64`
- `GRAFANA_ADMIN_PASSWORD`
- `ALERTMANAGER_TOKEN`

生产安全开关必须保持：

```env
NODE_ENV=production
ENABLE_DEV_AUTH_CODE=false
ENABLE_DEV_ADMIN_TOKEN=false
ENABLE_DEV_PAYMENT=false
WECHAT_PAY_ENABLED=true
FRONTEND_ORIGIN=https://bigdata.dtacloud.cn
CORS_ALLOW_ORIGINS=https://bigdata.dtacloud.cn
NEXT_PUBLIC_API_BASE_URL=/api
SERVER_API_BASE_URL=http://backend:4000/api
WECHAT_PAY_NOTIFY_URL=https://bigdata.dtacloud.cn/api/payments/wechat/notify
```

## 证书目录

服务器上创建：

```bash
mkdir -p secrets/wechatpay
```

放入：

```text
secrets/wechatpay/apiclient_key.pem
secrets/wechatpay/apiclient_cert.pem
secrets/wechatpay/pub_key.pem
```

容器内默认路径：

```text
/app/secrets/wechatpay/apiclient_key.pem
/app/secrets/wechatpay/pub_key.pem
```

## 执行顺序

1. 配置环境并跑生产门禁：

```bash
make audit-production
```

2. 如果这是已有服务升级，先做一次备份；如果是全新空服务器，可跳过这一步：

```bash
make backup
```

3. 启动生产候选环境：

```bash
make deploy
docker compose --env-file .env.production ps
```

`make deploy` 会先构建镜像，启动 postgres/minio，停止 caddy/web/backend，使用最新 backend 镜像执行全部数据库迁移，迁移成功后再启动整套服务。不要改成先启动新 backend 再手工迁移。

4. 验证基础健康：

```bash
curl -fsS https://bigdata.dtacloud.cn/api/health
curl -fsS https://bigdata.dtacloud.cn/api/health/deep
curl -fsS https://bigdata.dtacloud.cn/api/files/d1b1d1b1-2026-4000-9000-000000000001?v=original-logo >/dev/null
curl -fsS https://bigdata.dtacloud.cn/api/metrics && exit 1 || test "$?" -eq 22
```

5. 验证关键环境开关：

```bash
docker compose --env-file .env.production exec backend printenv NODE_ENV
docker compose --env-file .env.production exec backend printenv ENABLE_DEV_PAYMENT
docker compose --env-file .env.production exec backend printenv ENABLE_DEV_AUTH_CODE
```

期望：`production / false / false`。

6. 执行生产 QA：

```bash
docs/PRODUCTION_QA_AGENT_CHECKLIST.md
docs/MINIAPP_REAL_DEVICE_ACCEPTANCE.md
```

## 服务器 Agent 必测重点

- 超级管理员 `15842430688` 用真实短信验证码登录后台。
- 小程序微信登录、绑定手机号、onboarding。
- PC 小程序码登录。
- 小程序 JSAPI 真实小额支付。
- PC Native 真实小额支付。
- 微信支付回调成功后订单为 `paid`，支付单为 `succeeded`。
- 重复回调不重复发会员权益、不重复核销优惠券、不重复生成专家结算。
- MinIO 文件上传、下载、重启后仍可访问。
- 发票申请、后台手动开票、上传 PDF/OFD、用户下载。
- 异常中心、系统状态、Prometheus、Grafana、Alertmanager、Sentry。
- `make backup` 和一次临时环境恢复演练。

## QA 输出格式

服务器 Agent 最终给出：

- 部署版本/提交号。
- `.env.production` 已配置项清单，不输出密钥值。
- 通过项。
- 失败项：复现步骤、接口响应、日志、截图。
- 生产阻断项。
- 可延期项。
- 是否建议上线。

## 当前开发机已通过的本地门禁

- `backend npm run prisma:validate`
- `backend npm run typecheck`
- `backend npm run test:unit`
- `backend npm run test:business-closure`
- `web npm run lint`
- `web npm run build`
- `miniapp npm run typecheck`
- `miniapp npm run build:weapp`
- `make audit-production`

这些只能证明代码和本地 dev 闭环可用，不能替代服务器真实微信支付、小程序合法域名、HTTPS 回调和持久化卷 QA。
