---
url: /docs/agentbuff-stack/deployment.md
---
# 部署与验收

## 目标架构与当前状态

一个公开域名 → Web Worker（Astro 静态资产与路由）→ App / API 内部服务绑定。App 是 React SPA，API 是 Hono / Better Auth / tRPC。API 用 Hyperdrive 连接 Neon PostgreSQL，鉴权、支付和写后读取使用无缓存连接。

测试与正式环境已分别声明存储桶、任务队列、死信消费者和十五分钟维护入口；资源清单与离线发布检查已接入发布脚本和持续集成。**声明不等于创建或线上验收。** 正式环境仍保留示例域名；两个环境的 Hyperdrive 编号和发信地址仍待实际配置，发布检查会拒绝占位值。本地预览不受这项检查影响。

## 本仓库的官网域名与当前安排

用户于 2026-10-11 明确 `stack.agentbuff.dev` 用作 AgentBuff Stack 模板官网，现已授权发布静态官网和双语教程，暂不接真实产品。官网是 `apps/website` 的独立静态站，Wrangler 的自定义域名只声明在 `apps/website/wrangler.jsonc`。它不需要产品数据库、Hyperdrive、任务队列或模型密钥。

此前把这个域名当作产品测试入口是理解错误，已撤回 API / Web 的对应配置，产品 `staging` 恢复 `staging.example.com` 示例。它需在未来选定真实产品测试域名和资源后再配置。下面的产品离线检查只检查产品三个 Worker，不检查官网，也不能以官网域名代替产品的发布条件。

官网构建变量示例在 `.env.website.example`；教程位于官网 `/docs/` 下，演示地址留空并隐藏入口。`bun website:package` 在独立目录构建合并发布包，不覆盖本地预览；完成 Cloudflare 登录和域名权限核对后才上传。准备与发布命令见[官网配置](./website-showcase)。本地继续使用 4400 官网、4406 教程与 4410 模板演示。静态发布不创建产品数据库、任务队列或模型接入；构建和离线打包通过不能代替线上 DNS、证书与页面验收。

## 资源清单与创建职责

以下名称以站点编号 `agentbuff-stack` 为例；生成站使用自己的编号。测试环境是 `staging`，正式环境是顶层配置，对应 `production`。

| 资源 | 配置入口 / 绑定 | 创建与交接 |
| --- | --- | --- |
| 三个 Worker | `apps/{api,app,web}/wrangler.jsonc` | Wrangler 发布；Web 是唯一公开域名入口，App / API 通过服务绑定访问 |
| 内部服务 | Web 的 `API_SERVICE`、`APP_SERVICE` | 指向该环境的实际 Worker 名；测试环境默认在基础名字后加 `-staging` |
| 缓存与无缓存连接 | API 的 `HYPERDRIVE_CACHED`、`HYPERDRIVE_UNCACHED` | Terraform 管理；将对应环境输出的两个不同编号写入 Wrangler，不复制另一环境的编号 |
| 私有上传存储 | API 的 `STORAGE` | Terraform 可选上传资源，需启用 `uploads_enabled`；名称为 `agentbuff-stack-{环境}-uploads`，与生成器一致 |
| 任务队列 | API 的 `TASK_QUEUE` | 操作者预先创建该环境队列；模板名为 `agentbuff-stack-{环境}-tasks`，Wrangler 声明生产者与消费者 |
| 死信队列 | API 消费者与 `TASK_DEAD_QUEUE_NAME` | 操作者预先创建 `agentbuff-stack-{环境}-task-dead`；变量、主消费者的死信引用和死信消费者名称必须相同 |
| 定时维护 | API 的 `triggers.crons` | Wrangler 声明 `*/15 * * * *`；关闭新任务时仍保留历史任务、支付和通知的恢复入口 |
| 数据库 | Neon 与迁移连接 | 为每个站、每个环境准备独立数据库；原始连接凭据交给 Hyperdrive，迁移使用独立非池化连接 |
| 认证与邮件 | API 秘密及 `RESEND_EMAIL_FROM` | 当前环境分别保存认证秘密和邮件密钥；发信域名仍需在服务商验证 |
| 支付、统计、模型及可选模块 | [环境变量](./env)、[模块总览](./modules) | 按启用模块准备完整变量、真实价格与接口；资源检查不证明供应商可用 |

Terraform 只管理 Hyperdrive 与可选 R2，不管理 Worker 或域名。两个环境入口为 `infra/envs/staging`、`infra/envs/production`，仍须替换示例组织 / 工作区并核对自己的资源安排。队列创建和 Secrets 保存由操作者另行执行，不把它们混入 Terraform 的职责或新站生成流程。

环境变量、资源绑定、服务绑定和 Secrets 需按命名环境分别声明；定时入口具有继承规则，因此这里仍显式写出两个环境。规则依据[Wrangler 官方配置说明](https://developers.cloudflare.com/workers/wrangler/configuration/)。任务与死信消费配置参见[队列官方说明](https://developers.cloudflare.com/queues/configuration/configure-queues/)。这两份文档的核对日期为 2026-10-11。

## 环境隔离

每个新站使用独立数据库、认证秘密、Stripe 产品、邮件配置和 Worker 名。每个站再区分开发、测试、正式环境，沙箱与生产凭据分开。Worker 上的 Secrets 独立保存，不会读取电脑上的 `.env.local`。

公开域名、API 的 `APP_ORIGIN`、Worker 名与服务绑定必须一致。不要把 `DATABASE_URL` 当成生产 API 已使用的连接，生产 API 读取 Hyperdrive 绑定，迁移命令单独读取数据库连接。离线检查能发现配置编号相同，无法证明两个不同编号背后使用了不同数据库。

数据库应用账号、迁移所有者与网站用户分别管理。受限应用角色、完整任务流程及密码变更已在独立本地 SCRAM 实例验证；改密码 / 撤销连接权限都不会断开现有连接。两个 Hyperdrive 的源凭据和旧连接池需在所选环境一起处理，见[数据库角色与凭据](./database-roles)，真实云端验收仍待进行。

## 离线检查

先准备所选环境的 Wrangler 配置、实际资源编号、裸 HTTPS 域名和自己的发信地址。只检查名称与配置关系，不需要云端密钥：

```sh
bun deploy:check --target staging
bun deploy:check --target production --json
```

输出包含 Worker、资源名称、必需秘密的**变量名**及字段问题，不包含 Hyperdrive 编号或秘密值。检查缺失绑定、环境串用、主队列 / 死信引用、维护入口、服务名、存储命名和示例值。`onlineVerified: false` 表示没有验证资源存在、账户权限、Secrets 保存情况、数据库版本或供应商行为。模板初始配置检查失败是预期结果，不能用假的编号消除报错后当作真实验收。

服务端变量的类型、凭据组合和模块要求另行检查。命令使用自己的目标文件，报错只列字段；文件不提交：

```sh
bun --env-file .env.staging.local scripts/config-check.ts --target staging
bun typecheck
bun web:check
bun run test -- --run
bun lint
bun run format:check
```

为所选域名构建公开页，再检查发布产物。下面的地址仅展示用法，需换成已通过资源检查的真实地址：

```sh
APP_ORIGIN=https://staging.your-domain.com PUBLIC_SITE_URL=https://staging.your-domain.com bun run build
bun deploy:check --target staging --artifacts
bun run docs:build
```

产物检查要求邮件、工作台、公开页的入口文件存在且非空，并核对公开首页唯一的规范链接与目标域名相同。它不验证每篇文章的索引结果，也不证明部署版本已在线生效。构建本地预览时使用 `bun preview:build`，它恢复本地地址配置。

## 发布顺序

`bun deploy:staging` 与 `bun deploy:production` 在构建 / 上传前检查资源；正常构建会注入目标公开地址，再检查入口产物与首页规范链接，然后按 API → App → Web 发布。`--skip-build` 仍检查恢复的产物，拒绝本地或另一环境的首页链接。**这两个命令不会迁移数据库。**

持续集成默认只检查与构建。只有显式开启 `DEPLOY_ENABLED` 的发布任务才选择目标地址；构建产物和部署记录使用同一个已校验地址。发布任务恢复产物后，先运行资源 / 产物检查，再检查所需凭据、Cloudflare 认证与 Worker 离线打包，之后才进入原数据库迁移和上传流程。不会因为新加检查而自动开启部署。

资源创建、数据库迁移和 Worker 发布仍是独立操作；需要明确环境请求才能实际执行。发布不是原子切换，中途失败可能留下混合版本。数据库升级保持兼容，回退 Worker 版本不删除用户数据、不重写已应用迁移。

0012 已发布版本 → 当前完整增量 → 新 Worker → 旧 Worker 的本地兼容演练已通过；原账号、私有文件、收费任务 / 在途补投、原迁移和末尾故障回滚均使用实际数据库与运行时核对。复验入口与限制见[模板版本与升级](./template-upgrades#本地旧站升级与代码回退演练)。它只作用于自有一次性库，不代替所选真实环境的升级安排。

新增完整数据库归档与独立空库恢复已在实际本地 PostgreSQL 验证，使用同一导出快照核对表数据和迁移记录；配置、恢复命令、对象 / 外部事实边界见[数据库备份与恢复](./backup-restore)。独立文件对象检查点与私有结果恢复也已在受控本地 R2 绑定验收；本机归档可预览保留策略并人工清理，清理后保留归档的实际数据库恢复已验。这不替代下列云端验收，也没有自动设置 R2 生命周期。

## 云端验收与恢复

选定真实测试环境后，逐项保留时间、环境、资源与结果；不能以离线检查代替以下验收：

1. 核对实际账户、资源、独立数据库、绑定、Secrets、域名证书、发信域名和启用模块的数据库版本。
2. 注册 → 登录 → 上传 → 收费任务 → 检查结果 → 下载；验证另一用户 / 团队无法访问私有文件，邮件与支付回跳使用所选域名。
3. 在真实服务验证队列消费、死信、十五分钟维护、中断重试、失败返还、重复支付通知与退款；核对账本，不只观察页面提示。
4. 备份并在独立目标恢复数据库，核对文件元数据、对象、任务、账本和购买；验证对象保留 / 删除及密钥轮换安排。
5. 记录实际请求、对象、存储、队列、数据库与模型用量，依据所选服务套餐核算成本，并记录日期和来源。

I15 的云端运行、成本与恢复仍待真实环境验收；I16 的两个真实独立产品也未因此完成。Cloudflare、Neon 或第三方的免费额度属于当前服务政策，本模板不承诺永久免费。

认证版本密钥、旧登录重新认证与基础密钥的邮件用途已实际本地验收，操作范围和历史加密边界见[认证密钥轮换](./auth-key-rotation)。数据库角色、Cloudflare 绑定、外部供应商密钥及其轮换仍独立验收，不能以认证密钥切换证明全部权限已撤销。

## 文档部署

`bun run docs:build` 生成 `docs/.vitepress/dist`。它是独立静态文档站，当前没有产品域名 `/docs` 的自动服务绑定。设置 `DOCS_SITE_URL` 才生成正确 sitemap；不设置时 noindex。选择自己的文档域名与托管后，再设置链接与索引规则。
