VibeAny Docs
部署与运维

生产运维

安全执行预检、迁移、订阅积分定时发放、Webhook 回放和版本升级。

保障生产安全的前提,是明确每条命令能够证明什么。预检、数据库迁移、应用验证和端到端验收彼此独立。

预检内容

运行下面的命令,查看便于阅读的报告:

npm run preflight

自动化流程可以获取内容相同、敏感信息已脱敏的 JSON 报告:

npm run --silent preflight -- --json

预检会检查:

  • DATABASE_URLBETTER_AUTH_SECRET,以及不指向 localhost 的 NEXT_PUBLIC_SITE_URL
  • 每项已启用能力的配置完整性,包括支付、Google OAuth 和 One Tap、AI 图片生成、Turnstile、对象存储与邮件投递
  • 实时 PostgreSQL 连接
  • 会阻止已提交唯一索引落地的重复订阅、积分来源和 Webhook 事件记录
  • 整个仓库的 TypeScript 编译

报告会隐藏密钥值,以及常见连接字符串中嵌入的凭据。

预检不会执行迁移、检查源码格式、运行测试或构建应用。npm run validate 的范围也小于完整门禁:它只运行 Starter 当前的文档校验、i18n 校验和源码 lint。

发布前,请运行与本次改动相匹配、等同仓库 CI 的检查,包括类型检查、单元与集成测试、lint 和生产构建。依赖支付服务商的验收还必须包含真实 HTTPS Webhook、测试支付和数据库回读。

数据库变更只能使用迁移

任何环境都禁止直接推送数据库结构:

npm run db:push

该命令会有意报错退出。请改用以下流程:

# Edit src/lib/db/schema.ts
npm run db:generate

# Review and commit the new drizzle/*.sql and drizzle/meta changes
npm run db:migrate

生产迁移执行器会:

  • 在需要时创建 app_migrations 追踪表;
  • 直接读取 drizzle/ 下已提交的 .sql 文件;
  • 按文件名字典序执行尚未应用的文件;
  • 在同一个 PostgreSQL 事务中执行每个 SQL 文件并写入追踪记录;
  • 遇到追踪、SQL 或连接失败时立即停止。

执行器不支持向下迁移,也不提供分布式迁移锁。请备份重要数据,先在非生产数据库测试,同一时间只允许一个迁移进程操作同一个数据库。需要回滚时,请使用前向修复迁移或经过验证的数据库恢复方案。迁移文件名一旦被记录为已应用,绝不能再修改该文件。

Drizzle journal 用于记录生成与审查历史;生产迁移执行器则根据 SQL 文件名和 app_migrations 决定执行内容。

订阅积分调度器

Vercel 会按已提交的计划调用以下路由:

5 0 * * *
GET /api/cron/subscription-credits

任务每天 00:05 UTC 运行,但它不会每天发放积分。它会查找独立保存的月度发放边界已经到期的订阅,并发放配置好的月度积分。

只要配置了订阅产品,就应设置高强度且仅服务端可见的 CRON_SECRET。Vercel 会以如下形式发送:

Authorization: Bearer <CRON_SECRET>

路由行为:

结果状态
缺少 CRON_SECRET503
缺少 Bearer token 或 token 错误401
发放处理失败500
运行成功200,并返回发放与订阅数量

月度发放以订阅周期为锚点,使用与服务商无关的幂等来源,并在下一个发放边界或订阅周期结束时过期。任务延迟时可以补发多个边界,但每个订阅单次运行最多补发 24 次。发票类 Webhook 只更新计费状态,不会直接发放这些按月调度的积分。

运行结束后,检查函数日志,并回读受影响的 subscriptionscredit_transactions 数据行。如果没有积分到期,200 且发放数为零是正常结果。

支付 Webhook 运维

Stripe 和 Creem 共用一个应用端点:

POST /api/payments/webhook

对于新的 Webhook 流量,当前 PAYMENTS_PROVIDER 决定使用哪个签名验证器。处理器会验证未经修改的请求体、标准化服务商事件,并在应用计费变更前把投递身份写入 webhook_inbox

系统按服务商加事件 ID 或载荷哈希去重。成功处理过的事件再次投递时,会返回 200deduped: true。处理时会为每条事件占用两分钟处理租约;处理器失败时会尽可能释放租约,尚未处理且已经过期的租约可以由后续投递重新取得。

响应含义
200, deduped: false投递已接收并处理
200, deduped: true投递已处理,或当前由另一次尝试持有
400缺少签名或签名无效
503所选服务商配置不完整
500验签成功,但应用处理失败

回放失败事件时:

  1. 确认端点和当前服务商与发送方一致。
  2. 确认签名密钥属于这个准确的端点和测试模式或生产模式。
  3. 从服务商控制台或开发 CLI 回放,不要修改事件载荷。
  4. 检查 HTTP 响应和应用日志。
  5. 回读 webhook_inbox,以及相关的 subscriptionsorderscredit_transactions 数据行。

在本地转发 Stripe 事件:

stripe listen --forward-to localhost:3000/api/payments/webhook

本地监听器输出的签名密钥只能用于对应的本地环境。

升级 Starter

package.json 是已安装版本的权威来源。升级经过定制的项目时,请谨慎操作:

  1. 阅读跨越的每个版本的 changelog。
  2. 提交或备份应用代码和数据库数据。
  3. 在独立分支应用版本改动,不要直接覆盖定制文件。
  4. 使用已提交的锁文件运行 npm ci
  5. 审查每一个新增 SQL 迁移和 Drizzle journal 记录。
  6. 数据库变更只能通过 npm run db:migrate 执行。
  7. 运行 npm run starter:check 和覆盖本次修改的测试。
  8. 先部署并验证非生产环境,再进入生产环境。

跨过主版本或修改过购买的源码,都可能需要手动集成。Starter 不会自动把上游改动合并到定制应用中。

本页目录