---
url: /docs/agentbuff-stack/operator-notifications.md
---
# 站主运营通知

站主可以选择将已提交的任务成功 / 失败、积分包付款与订阅账单付款发送到一个固定 Discord 频道。该模块默认关闭，与个人任务邮件、营销订阅、活动统计分别配置。管理员可以在后台查看投递记录；普通用户不能配置目的地或发送消息。

本地实际任务、受控付款与捕获接口用于验证实现。捕获回执不能证明真实频道收到了消息；真实供应商和云端定时维护仍需独立验收。

## 配置与迁移

公开开关位于 `packages/core/website.ts`：

```ts
notifications: {
  taskEmail: false,
  preferenceVersion: "2026-10-11",
  retentionDays: 30,
  operator: {
    enabled: false,
    since: null,
  },
}
```

启用时设置 `operator.enabled=true`，并将 `since` 改为明确的 UTC 时间，例如 `2026-10-11T00:00:00Z`。它决定首次纳入的业务事件起点，不使用部署时间猜测，不自动补发之前的历史事件。时间与保留期共同限制扫描范围。

服务端秘密变量为 `DISCORD_NOTIFICATION_WEBHOOK_URL`，仅接受 `https://discord.com/api/webhooks/频道通知编号/令牌` 这一固定格式的标准地址。完整地址内的令牌是秘密，不写入公开配置、浏览器、通知表或日志。没有任意用户地址、私有主机、额外端口、查询参数或自动重定向路径。启用缺少地址 / 起点或地址不合格时，配置检查明确失败。

先在目标环境完整升级到 `0021_operator_notifications.sql`，再重建 API、工作台和公共页。0021 新增最小投递记录及独立订阅检查时间表，保留所有旧迁移。正常预览主库仍为 0012，尚未应用 0020 / 0021，通知开关保持关闭；此时页面和维护不会读取这两张站主通知表。

云端需将秘密变量注入 API Worker，并配置现有每 15 分钟维护入口。没有新增通知队列，也没有公开测试发送接口。支付通知依赖已正确配置、验收的原 Stripe 支付入口，设置通知地址不能开通收款。

## 事件来源与付款凭证

| 事件 | 纳入依据 | 不纳入的情况 |
| --- | --- | --- |
| 任务完成 / 失败 | 已保存终态、完成时间及当前执行租约版本 | 取消、中间重试、未完成、起点之前和过期任务 |
| 积分包付款 | 原购买已付且发放已提交，金额 / 币种 / 模式与对应积分流水相符 | 待付、仅回跳成功、缺少对应实际发放流水 |
| 订阅账单付款 | 原始通知验签后重新核对当前账单、客户 / 本站订阅、完整付款分配和实际成功收款 | 零元、待付、余额抵扣、线下付款记录、客户或模式不符、不完整分页 |

个人和团队的已核实订阅账单都可形成站主通知；团队付款不会记到某个成员的个人活动统计。付款校验与个人统计共用，但启用、接收者和授权分别检查。运营通知不要求个人开启任务邮件、营销或活动统计，也不会替用户保存这些选择。

记录的是原始付款确认，不是扣除退款后的净收入、利润、订阅留存或阅读证明。通知不改写订阅权限、不额外发积分，不替代财务流水与审计。后续退款属于另一个业务事件，本阶段不提供退款通知。

漏回调恢复使用独立检查时间，每轮最多检查三个有效个人或团队客户，同一客户至少间隔 15 分钟；失败也让出轮换位置。每次最多读取 1,000 张已付账单，每张最多核查 100 个付款分配。按实际付款时间筛选，早期创建但近期付款的账单仍可恢复；重复页、超限和缺页不假报完整恢复。该检查不占用用户账单操作租约，不复用个人活动统计的同意或检查时间。

## 消息内容与去重

消息只包含固定事件名称、内部任务 / 购买 / 账单编号、付款最小货币单位金额、币种、测试 / 正式模式和本站管理员入口。没有姓名、邮箱、团队名称、原文件名、输入、输出、提示词、附件、签名下载链接、通知令牌或供应商原始错误。明确禁止自动提及频道成员。

任务使用任务编号、当前执行租约版本和结果组成事件键；付款使用购买或账单编号与固定类型。数据库唯一键处理重放与并发，发送前再次核对任务或购买。任务重试替换旧执行时，旧未发通知跳过，新终态可产生新的事件。已核实订阅付款保存最小凭证后独立投递。

目标地址、环境、认证密钥、网站 Origin、起点与消息版本通过 HMAC 摘要绑定。配置变化后旧待发送记录跳过，不把旧消息改投到新频道。管理员入口仍需登录及最新管理员权限，不因收到链接获得访问权。

## 投递状态与排查

| 状态 | 含义与下一步 |
| --- | --- |
| 等待发送 | 业务事件已入库，维护尚未领取 |
| 发送中 | 一次两分钟租约，其他维护不能同时领取 |
| 限频等待 | 明确收到 429；按要求等待且至少 15 分钟，最多三次尝试 |
| 渠道接口已接收 | 收到有效消息编号；不代表有人阅读 |
| 已拒绝并停止 | 明确拒绝、耗尽尝试、过长限频等待或本地捕获缺失 |
| 接收未确认并停止 | 断网、超时、服务错误、缺少有效回执或发送租约过期；不自动重发 |
| 已跳过 | 业务来源、保留范围或绑定配置已变化 |

请求超时十秒，不跟随重定向；要求 `wait=true` 取得实际消息回执。[Discord 官方说明](https://docs.discord.com/developers/resources/webhook)于 2026-10-11 核对：执行通知接口可等待返回消息；默认不等待的成功响应不能提供同等回执依据。本模块只接受带有效消息编号的返回。

Discord 没有本模块可用的请求幂等键。响应丢失不能证明消息没发出，因此只有明确限频才自动重试；请求结果不确定或租约过期时停止。不会用新的事件键绕过这项限制。回写还需匹配本次未过期租约，迟到回执不能覆盖已停止的记录。限频要求超过一天时停止，不提前截断等待时间再发送。

管理员后台显示每页 20 条、状态、次数、事件时间、限频的下次时间及有效回执，可刷新、翻页。读取检查最新数据库角色、验证状态和封禁；撤权后原会话不能继续读取，接口限频返回明确响应。列表不暴露目标摘要、秘密地址或供应商错误正文。当前没有强制重发按钮；未确认时先检查实际频道与供应商记录，再决定人工处理。

## 保留与本地验证

列表隐藏起点之前或超过 `retentionDays` 的事件；每轮最多删除 100 条过期投递。订阅检查时间表也按最后检查时间清理过期行，每轮最多 100 条。默认保留期 30 天，允许 1—90 天；关闭模块、积压或维护故障可能延迟物理删除。清理后的旧业务不会再次进入扫描。

站主记录不存个人账号编号，不随用户 / 任务删除立即级联，而按本模块保留范围清理；多类型的来源编号仅用于排查，不是跨表外键。供应商客户检查标识同样仅用于轮换。财务和管理员审计继续遵守原独立规则。正式隐私说明需准确披露配置频道的提供方、用途和保留范围。

开发运行时总是注入 `LOCAL_OPERATIONS`，消息写入独立本地 `operations-outbox.jsonl`，即使环境提供真实地址也不会外发。开发环境缺少捕获时不回退网络；非开发环境意外带捕获绑定也会停止。捕获文件属于本地排查资料，不能提交或公开分享。

```bash
bun --cwd apps/api validate:operator-notifications
```

验证器创建自己的 loopback 临时数据库，应用完整迁移，运行实际 Worker、Queue、R2、原始签名付款回调及受控 SDK 请求。覆盖成功 / 失败任务、积分包已提交发放、零元排除、并发账单、分配分页、通知表故障后的续费恢复、捕获故障停止、普通角色禁止读取与原结果下载。结束删除临时资源；`--ui` 额外构建专用管理员页面供桌面 / 手机与浅 / 深主题验收。不会提升正常预览账号或升级主数据库。

本地验证与真实外部验收分别记录：实际频道消息回执、真实限频 / 故障、部署秘密及云端维护仍需验收。个人邮件配置见[任务邮件通知](./task-notifications)。
