受众领域模型(总纲)
状态:现行模型(2026-10-07 重写)。本文是 Herald 领域模型的唯一总纲:术语、边界、 受众层扩展全貌。关系的逐项详设(流程图 / 矩阵 / 参数表)在 受众订阅与投递中枢(下称「关系详设」); 概念分层与职责边界的裁决在概念边界与分层审计; Phase 0-9 管道改造的执行历史在现状审计(存档)。 铁律:方案变了先改本文——代码与本文不一致时,以本文为口径提批修正。
1. 定位
Herald 是轻量的通知编排与投递基础设施。它决定的不只是「发出去」:谁、什么时候、通过什么渠道、以什么强度、是否聚合、是否过滤、是否升级、是否去重——这些编排决策由 Herald 收口,投递管道(Phase 0-9 已落地)是这一面的地基(见现状审计)。
在此之上,Herald 的定位是统一订阅与投递中枢:从「应用主动推送」补全为「被通知者做主」。应用(业务系统集成方)只持有受众 ID;谁在什么渠道、以什么频率收到什么品类,由受众自己的关系决定,而不是由调用方写死。
旧:应用 ──「发到 telegram:123456」──> Herald ──> 渠道
新:应用 ──「告警品类,通知 user:alice」──> Herald ──> 关系过滤 ──> 联系面 ──> 渠道
▲
受众自己的订阅/偏好/退订决定这里放行什么2. 术语契约(唯一口径)
文档与代码术语一一对应,一个词只有一个含义。全站文档(指南 / 架构 / API / 设计)一律按本表用词:
| 术语 | 代码标识 | 含义 |
|---|---|---|
| 受众 | audience(引用 group:<id> / user:<id>) | 身份主体,全系统唯一;应用只持受众 ID,不碰渠道凭据 |
| 接收人 | recipient | 受众成员的具名个人(recipients 静态配置实体)。注意与指派关系里的「接收者角色」区分——接收人是身份,接收者是关系角色 |
| 端点 | Endpoint | 接收人的静态投递地址(type + target) |
| 联系面 | ContactSurface | 受众在运行时绑定的可达渠道凭据(TG chat_id、邮箱、公众号 openid、RSS 私密 token),带 pending/active/invalid 状态 |
| 订阅关系 | RelationSubscription / Subscribe() | 受众主动勾选的关系:品类×渠道×频率,完全自主可退订;关系中的受众角色叫订阅者(subscriber) |
| 指派关系 | RelationEnrollment / Enroll() | 被动纳入的关系:管理员分组广播、运营触达、系统通知;关系中的受众角色叫接收者(recipient role) |
| 策略位 | Policy(AllowUnsubscribe / MustDeliver) | 挂在关系上的权利位:退订权、必达标记 |
| 入口来源 | Source(bot / wechat_mp / preference_center / admin / app:<name>) | 关系与绑定经由哪个入口适配器进来,审计按此记 |
| 品类 | category | 业务通知的分类维度(告警 / 账单 / 域名 / 公告 / 系统 / 营销),关系的分类轴 |
| 渠道 | channel | 触达手段(telegram / email / 站内信 / RSS / 短信 / 电话),带侵扰度、实时性、投递方向(push/pull)三个属性。渠道≠provider:渠道经渠道块展开为 provider 实例,同一渠道可换实现(email→smtp 或 resend) |
| 渠道块 | channels 配置块 | 命名渠道 → provider 实例集合的静态展开(既有投递配置;与品类维度正交,见 §6) |
| 偏好 | Preference | 订阅关系上的品类×渠道×频率三元组选择 |
| 聚合 | Digest | 按受众+品类+时间窗把多条事件收成一条摘要 |
| 紧急度 | Urgency(routine / normal / urgent / critical) | 消息的紧急级别,决定允许的渠道强度区间 |
| 侵扰度 | Intensity(L0–L5) | 渠道的打扰强度阶梯:拉式 < 邮件 < 站内信 < IM < 短信 < 电话 |
| 投递模式 | escalation / fixed / parallel | 升级链 / 固定单渠道 / 多渠道并行,三选一可配 |
| 频控 | once / throttle / always | 去重频控三档:仅一次 / 窗口节流 / 允许重复 |
受众是身份;订阅者/接收者是受众在某条关系里的角色。不存在平行的「订阅者」身份实体——应用侧只对接一套受众 ID。
3. 核心链路
Event ──> Rule ──> Notification ──┬──> Audience(受众引用)
└──> Template(渲染)
│
受众层(§5):关系过滤(订阅/指派 × 渠道矩阵)
└──> 联系面(可达凭据,§5.2)
│
▼
Routing(展开成投递任务)──> 去重/频控(§8)──> 投递模式(§7)
│
▼
Delivery Task ──> Queue ──> Worker ──> Provider
│
旁路:Digest 时间窗聚合(§10)/RSS 拉式出口(§10)4. 概念边界
Notification ≠ Delivery Task 一次通知 ≠ 一次渠道投递
Audience ≠ Channel ≠ Provider 通知谁 / 触达手段 / 怎么发送,三件事
接收人 ≠ 端点 具名个人 ≠ 一条静态投递地址
端点 ≠ 联系面 Endpoint 是静态配置地址;ContactSurface 是
运行时绑定、带状态、可失效重绑的凭据
订阅 ≠ 指派 主动勾选与被动纳入同表不同义:退订权、
渠道矩阵、审计全部分开(关系详设 §4)
关系 ≠ 联系面 意愿/义务(能不能收)≠ 可达性(收得到吗)
Routing ≠ Delivery 决策(谁收到什么)≠ 执行(投出去、重试)
规则升级 ≠ 强度升级 规则引擎升级回答「叫谁」;强度升级链回答
「怎么叫得更响」,两者正交可叠加5. 受众层
5.1 身份:受众 → 接收人 → 端点
受众有两级引用形态:group:<id>(群组,成员解析见通知群组设计)与 user:<id>(具名个人)。静态配置模型:
audiences: # 受众 → 接收人
ops:
recipients: [alice, bob]
recipients: # 接收人 → 端点
alice:
endpoints:
- { type: telegram, target: "123456" }
- { type: email, target: "alice@example.com" }配置在启动时校验,非法即拒起(user: 引用绝不静默落空)。这张静态表是联系面的种子(见下节);无联系面扩展的既有用法行为完全不变。
5.2 联系面(ContactSurface)
渠道凭据的运行时挂点。应用侧只经手受众 ID 与一次性绑定 token,永不接触凭据明文;换绑需旧渠道确认,防止一条深链抢走别人的通知渠道。
| 状态 | 含义 | 投递行为 |
|---|---|---|
pending | 绑定发起未核销 / 换绑待旧渠道确认 | 不投 |
active | 已核销可用 | 按关系投递 |
invalid | 外部平台判定失效(对账 / chat 不可达 / 取关回流) | 不投,等待重新绑定 |
绑定走 bot deep-link 一次性 token(15 分钟过期、单次有效);每个受众随注册自动持有一份 RSS 私密 token(零绑定成本)。流程图与规则细节见关系详设 §3。已落地:core/audience.SurfaceRegistry(批次 2)。
5.3 关系(Relation)
投递的唯一合法依据:发送时校验「关系允许 × 联系面绑定」的交集,交集为空不投并审计。两种关系即使实现同表,语义、退订策略、审计也必须分开:
| 订阅 subscription | 指派 enrollment | |
|---|---|---|
| 发起方 | 受众自己勾选 | 管理员 / 运营 / 系统 |
| 退订权 | 完全自主 | 底线保留(见下) |
| 接口 | Subscribe() | Enroll() |
指派关系的底线:营销/运营类必须可退订;系统必达类明示标记且仅限法定/合同/安全义务内容;渠道与频率上限用户始终可管。关系行带 type + source + policy,查询与审计按类型分,不做万能关系接口。已落地:core/audience.Registry(批次 1)。数据模型与流程图见关系详设 §4。
6. 渠道与渠道×关系矩阵
渠道(触达手段)与 provider(发送实现)分开:渠道是受众视角的词,provider 是集成视角的词;既有 channels 配置块承担「命名渠道 → provider 集合」的静态展开,品类维度(告警/账单/…)随集成者 API 落地注册(关系详设 §13.2)。
可用渠道随关系类型走,不是一套。发送时校验三方交集:
投递目标 = 受众绑定的联系面 ∩ 关系类型允许的渠道 ∩ 紧急度允许的强度区间| 渠道类 | 订阅型 | 指派·系统必达 | 指派·营销/运营 |
|---|---|---|---|
| 即时类(IM/短信/推送) | ✅ 用户自选 | ✅ 多渠道并行保必达 | ❌ 禁用 |
| 邮件 | ✅ 用户自选 | ✅ 兜底并行 | ✅ 默认渠道,低频可退订 |
| 应用侧(webhook→站内信) | ✅ 用户自选 | ✅ | ✅ 默认渠道,低频可退订 |
| 拉式(RSS) | ✅ 仅订阅型 | ❌ | ❌ |
每格默认策略、校验时机与违规报错见关系详设 §5。矩阵与过滤已落地(批次 4:矩阵入 Enroll 门 + Filter.Allow 发送前复核;expandRef 管道挂接随批次 11 触发面——现 /notify 无品类维度可过滤)。
7. 强度×紧急度与投递模式
渠道不是平的。侵扰度 L0–L5 阶梯(RSS 拉取 → 邮件 → 站内信 → IM → 短信 → 电话)配消息紧急度四级(例行/一般/紧急/关键),紧急度决定允许的强度区间;匹配规则独立成策略件,不散落在 provider 里。
用户偏好可降不可升:可以在紧急度区间内往下关渠道,不能往上开;关键级有保底渠道(配置指定、偏好中心明示)。三种投递模式按品类/关系类型/单次触发可配,策略件同一入口不同执行器:
| 模式 | 行为 | 默认 |
|---|---|---|
| 升级链 escalation | 未应答逐级升强度,应答即停 | 紧急/关键 |
| 固定单渠道 fixed | 只走指定的一种渠道 | 例行/一般 |
| 多渠道并行 parallel | 一次全发保必达 | 系统必达类强制 |
阶梯图、匹配矩阵、升级链参数与去重折叠的先后关系见关系详设 §6。已落地(批次 9,core/audience.DeliveryPolicy 策略件 + BuildPlan/RunPlan 执行器;触发面接线随批次 11)。
8. 去重与频控
与聚合分工:Digest = 时间窗聚合不同消息;去重 = 相同消息折叠。去重发生在投递管道之前、升级链之前——10 条重复告警先折叠成 1 条再计应答与升级。
三层:事件幂等(event_id 重复触发只投一次)、内容折叠(同品类同内容窗口内折叠带计数「×10」,原始事件列表保留可审计)、状态机去重(状态型告警按翻转发,挂→恢复→再挂才再发)。频控三档可配(once / throttle / always,按品类/关系类型),用户偏好可收窄不可放宽。
既有能力:内容指纹去重与请求幂等键已上线;事件幂等/折叠/状态机/三档频控已落地(批次 10,core/dedup.Gate 闸序 + config.DedupConfig 品类档位与窗口覆盖表)。用户偏好收窄的 Narrow 格已备,端点随批次 11 偏好面接线。细节见关系详设 §11。
9. 偏好与入口
订阅者在偏好中心自助勾选「什么品类 → 什么渠道 → 什么频率」,默认策略随品类给(系统必收、营销默认每周汇总、告警可降频不可静默)。偏好修改入口不唯一——bot 命令、公众号关注事件、应用内勾选、偏好中心都是来源适配器;Herald 是关系的权威登记处,所有入口收敛为注册表里的关系变更,取关必须回流(停止一切投递),外部平台状态定期对账。默认策略表与适配器规则见关系详设 §7-8。偏好模型已落地(批次 3,core/audience 的 Frequency/Preference/DefaultPolicy 与读写 API);来源适配器已落地(批次 8,SourceAdapter + bot/公众号/应用内三个入口端点 + 外部状态对账)。
10. 触达形态:Digest 与 RSS
Digest(批次 6):按受众×品类×时间窗(每日/每周)把零散事件收成一条摘要,走既有投递管道(摘要也享受重试/审计);实时类豁免直投,系统必达永不聚合。已落地(core/digest:窗口翻转严格晚到语义、Resolve 豁免裁决、digest:<品类> 模板换皮、FlipLoop 定时器 + 可选 redis 租约选主——无 redis_addr 单机直跑)。
RSS 拉式(批次 7):零绑定零推送的天然偏好通道。公共 feed 每品类一个(/feeds/<品类>.xml,只含无受众引用的公开内容);私密 feed 带受众的 rss_token(/feeds/private/<rss_token>.xml,批次 2 的重置即旧地址失效语义直接生效),账单等个人内容走这里;频率=阅读器轮询,Herald 不推,天然无骚扰;仅订阅型关系可用——指派内容不进 feed。已落地(core/feeds 拉式投影存储 + RSS 2.0 渲染,/feeds/** 端点,投递管道对 rss 类渠道就地投影不产生 provider 任务;可见性在读取时判定——token 归属 + 关系注册表×渠道矩阵复核,取关即从下一次拉取起消失;多地址容灾按边界审计 §4 归阅读器侧)。
11. 投递与审计
投递侧已经落地的形状:任务状态枚举(delivered / failed / dead,重试中 retrying)、错误六类词汇(temporary / permanent / rate_limited / authentication / invalid_request / timeout)决定重试与终态、429 带 Retry-After 退避、可重试失败异步重新入队(next_retry_at 队列侧持留,worker 不睡退避)。审计侧已按关系详设 §12 补齐:关系类型与入口来源快照进通知→任务→投递日志全链、关系/联系面变更流水(core/audit,订阅/指派/退订与绑定/换绑/失效六类事件,按类型与受众分读)、去重折叠明细(delivery.deduped,带内容指纹)——审计回答「这条订阅从哪个入口来、这次投递依据哪条关系、为什么失败、谁在何时改了什么」。审计补齐已落地(批次 5);发送侧关系上下文随批次 8/11 触发面填充。
12. 集成者 API
全部模型能力配可编程配置 API:每个集成应用一个 app 命名空间(品类/模板/策略互相隔离),app token 按权限分级(config / trigger / query);配置、触发、查询三组端点与升级链、去重、渠道矩阵等策略件同口径;Go SDK 首发,webhook 回调带回投递结果与退订事件。契约草案见关系详设 §13,集成指南随批次 11 落地 docs/guide/integration.md。已落地(批次 11 增量一~八;2026-10-08 阶段③集成方对接验证收官——事件接入适配面与回调回带 event_id 已贯通)。
13. 落地状态(诚实口径)
| 能力 | 状态 | 证据 |
|---|---|---|
| 通知管道(路由/队列/worker/重试/错误分类/请求幂等) | ✅ 落地 | 现状审计 Phase 0-9 |
| 关系模型与受众注册表 | ✅ 落地 | 批次 1(3fc1a82),core/audience.Registry |
| 联系面与绑定(token/换绑/RSS token) | ✅ 落地 | 批次 2(19cf16c),core/audience.SurfaceRegistry |
| 偏好中心(品类×渠道×频率、默认策略表) | ✅ 落地 | 批次 3(4df837a),core/audience.PreferenceRegistry |
| 渠道×关系矩阵与投递过滤(四族分类、Enroll 门强制、发送前复核) | ✅ 落地 | 批次 4(4b18b4a),core/audience.Filter;expandRef 挂接已随批次 11 贯通 |
| 投递审计补齐(变更流水、去重折叠明细、关系快照进任务与日志) | ✅ 落地 | 批次 5(de05e94),core/audit + SetRecorder/SetFoldAudit |
| Digest 时间窗聚合(窗口翻转、豁免裁决、摘要模板、翻转循环与可选租约) | ✅ 落地 | 批次 6(3204e90),core/digest + SetDigest/FlushDigest |
| RSS 拉式渠道(公共/私密 feed、读取时可见性、拉式投影) | ✅ 落地 | 批次 7,core/feeds + /feeds/** 端点 + SetFeeds 投影;token/关系注册表随批次 8 已共享接线 |
| 来源适配器(bot /start /stop、公众号关注事件、应用内勾选、取关回流全停、外部状态对账) | ✅ 落地 | 批次 8,core/audience.SourceAdapter/Reconciler + api 三个入口端点 + telegram/wechatmp probe |
| 去重与频控(事件幂等、折叠账本、状态机、三档频控与品类默认/覆盖表) | ✅ 落地 | 批次 10(3c6c395+ca6ee39),core/dedup.Gate + config.DedupConfig 覆盖表 |
| 强度与模式(强度阶梯、紧急度区间、电话双重同意门、三模式执行器) | ✅ 落地 | 批次 9(0c20459),core/audience.DeliveryPolicy/BuildPlan/RunPlan;触发面接线已随批次 11 贯通 |
| 集成者 API 与 Go SDK | ✅ 落地 | 批次 11 增量一~八,api/handler_apps.go(config/trigger/query 三面 + events 适配面 + callback)+ apps-sdk/go + docs/guide/integration.md;阶段③集成方对接验证(0096be4)闭环 |
在途能力的配置项与端点尚不存在,勿据本文档配置生产;落地一批,本文状态表与对应详设同步更新一批。(截至 2026-10-08,§15 批次 1-11 与三阶段验证已全部落地,本表无在途行。)
14. 沿革
Phase 0-9 管道改造的原计划书(「Audience 领域模型:架构改进计划书」)已收官,执行记录与留批拍板在现状审计存档,计划原文由 git 历史保存。2026-10-05 立项受众层扩展(统一订阅与投递中枢),2026-10-07 本页由计划书重写为现行模型总纲;关系详设承接全部新增能力的逐项设计。