Skip to content

03 · 事件、Kind 与标签

Buzz 以 Nostr event 作为跨端协议原子:事件 ID 是规范序列化后的哈希,签名证明作者,kind 决定语义,tags 承载可索引关系,content 承载正文或结构化载荷。Buzz 的关键扩展不是改变这个原子,而是建立一套庞大的 Kind 注册表和集中式隐私策略。

1. 基本数据模型

text
Event {
  id, pubkey, created_at, kind,
  tags: [[name, value, ...], ...],
  content,
  sig
}

StoredEvent {
  event fields...,
  received_at,
  channel_id?,
  private_verified
}

StoredEvent 增加 Relay 侧事实:接收时间、解析后的频道和私密校验结果。客户端不能签名这些字段,它们属于存储信封。

2. Kind 分类

Nostr 以数值范围定义生命周期,Buzz 又在范围内分配产品语义:

类别典型 KindBuzz 用途
普通事件19文本/频道消息
Ephemeral200012000224200presence、typing、observer frame,不入长期事件表
Replaceable010100profile、agent profile,同作者同 kind 保留新值
Parameterized replaceable30000+persona、workflow、push lease、Git repo announcement,以 d tag 定坐标
Buzz command/event40002+消息 V2、DM、job、workflow run、audit、huddle、media

“可替换”不是客户端约定。数据库写入使用事务与社区级 advisory lock,保证同一 replaceable coordinate 的并发更新不会留下多个权威版本。

3. 注册表比常量表多做了什么

buzz-core/src/kind.rs 同时承担三种职责:

  1. 数值到语义的单一注册点。
  2. ALL_KINDS 一类枚举集合,为验证/文档/测试提供闭集。
  3. 隐私集合,驱动通用读写门控。

重要隐私集合包括:

集合语义
AUTHOR_ONLY_KINDS只有作者自己可读取,例如某些本地/私有状态
P_GATED_KINDS读者必须是作者或出现在 p tag 中
SHARED_GATED_KINDS作者与读者必须共享指定关系/空间
RESULT_GATED_KINDSjob result 需要与请求/参与主体对应

把 kind → privacy policy 集中,降低 REQ 与 fan-out 各写一份易漂移分支的风险。但新 kind 若忘记进入正确集合,也会形成系统性漏洞,因此注册表测试非常重要。

4. 标签是关系索引

Buzz 常见 tag:

Tag作用
h频道/群组 ID,是绝大多数协作事件的空间坐标
p公钥参与者、提及者或可见者
e事件引用;NIP-10 用 marker 区分 root/reply
aparameterized replaceable coordinate 或长寿命对象引用
dparameterized replaceable 事件的逻辑 ID
t主题标签
repo / commitdiff、patch 与 Git 对象的关联

Relay 不会盲信 h。某些事件必须全局,带 h 反而拒绝;某些事件必须有频道,缺失就拒绝;父回复必须属于同一社区/频道。

5. Filter 语义

Nostr REQ 可以带多个 filter:filter 之间是 OR,同一 filter 的字段之间是 AND。buzz-core::Filter::matches 还处理:

  • event ID 和 pubkey 的前缀匹配。
  • #x 泛型 tag 过滤。
  • filter 没写 #h 时,可用 StoredEvent.channel_id 做内部频道匹配。
  • 对 DV/Agent 指标等敏感 kind 引入 reader-aware gate。
text
REQ [filter A, filter B]
       │          │
     AND fields  AND fields
       └──── OR ───┘

Filter 匹配只是“候选事件是否符合订阅表达式”,不是最终授权。查询和 fan-out 之后还会跑 event_visible_to_reader 一类安全门。

6. 签名验证

verification.rs 的次序是:

  1. 按 Nostr 规范重新序列化并计算 event ID。
  2. 常量时间比较/验证 ID 是否一致。
  3. 用作者公钥验证 Schnorr 签名。

这是 CPU-bound 工作,Relay 注释要求放进 spawn_blocking,避免大量签名验证阻塞 Tokio reactor。认证事件与普通事件都不能只验证签名而跳过 ID 重算,否则攻击者可能签署与宣称 ID 不一致的载荷。

7. 协议扩展地图

当前注册表大致覆盖:

  • Agent/profile/persona/team/engram/reminder/metric。
  • NIP-29 group admin、membership、moderation 与 discovery。
  • stream/forum/DM、edit、pin、bookmark、scheduled message、canvas、diff。
  • jobs 与 results。
  • workflow definition/execution/trigger/approval。
  • huddle、媒体、Push lease。
  • Git repository、patch、issue、PR 与 refs 通知。

这说明 kind.rs 已经成为 Buzz 的“协议级领域目录”。优点是跨语言客户端可以稳定对齐;代价是兼容性、隐私和生命周期必须一起治理。

8. 事件不是所有事实的唯一载体

有三类例外必须记住:

  1. 派生关系表:成员、线程、反应、工作流运行等会有数据库权威状态。
  2. Ephemeral:presence/typing 不进入长期事件表,重启后靠 TTL/重新发布恢复。
  3. 派生通知:Git manifest event 只是 S3 CAS 提交后的可观察通知,不能反过来成为 refs 权威。

9. 源码入口

独立源码研究笔记 · 非 Buzz 官方文档