02 · 总体架构与依赖边界
Buzz 是一个“中心 Relay + 多种边缘运行时”的系统。中心并不做所有事:Relay 管理权威事实与实时路由;Desktop 管理本地能力;Agent harness 把频道事件翻译成 ACP prompt;Push gateway 独占 APNs 凭证;Mesh 让 stateful 工作负载跨 Relay 节点迁移或互联。
1. 运行时拓扑
┌──────────────── client / edge ───────────────────────────────┐
│ Desktop(Tauri+React) Web(React) Mobile(Flutter) CLI │
│ │ │ │ │ │
│ ├── managed ACP/Agent/MCP sidecars │
│ ├── local Git / media / keychain │
│ └── optional huddle audio + mesh compute │
└───────────────┬───────────────────────────────────────────────┘
│ WS / HTTP / Git smart HTTP
┌───────────────▼──────── Relay pod ────────────────────────────┐
│ tenant resolve → auth → ingest/query → access gates │
│ subscriptions → local fan-out → Redis cross-pod publish │
│ workflow / media / git transport / huddle gateway │
└──────────────┬──────────────────┬─────────────────────────────┘
│ │
┌────────▼────────┐ ┌──────▼──────┐
│ PostgreSQL │ │ Redis │
│ facts + views │ │ coordination│
└────────┬────────┘ └─────────────┘
│
┌───────▼─────────────┐ ┌────────────────────┐
│ S3-compatible store │ │ Push Gateway + DB │
│ media + Git packs │ │ APNs custody │
└─────────────────────┘ └────────────────────┘2. Rust workspace 分层
27 个 crate 可以按依赖方向理解,而不是按字母排序:
| 层 | 代表 crate | 角色 |
|---|---|---|
| 领域/协议 | buzz-core | Event、Filter、Kind、Channel、Tenant、NIP 扩展模型 |
| 基础服务 | buzz-db、buzz-pubsub、buzz-auth、buzz-search、buzz-audit | SQL/Redis/认证/搜索/审计的可复用能力 |
| 服务编排 | buzz-relay、buzz-push-gateway、buzz-pair-relay | 对外监听、路由、生命周期与依赖接线 |
| SDK/客户端 | buzz-sdk、buzz-ws-client、buzz-cli、buzz-admin | 事件构建、协议客户端与运维入口 |
| Agent | buzz-acp、buzz-agent、buzz-dev-mcp、buzz-persona、sprig | harness、模型循环、工具、persona、整合发行物 |
| 扩展能力 | buzz-media、buzz-voice、buzz-workflow、buzz-relay-mesh | 文件、音频、自动化与节点互联 |
| Git | git-credential-nostr、git-sign-nostr | NIP-98 凭证与 Nostr Git 签名 |
| 验证 | buzz-conformance、buzz-test-client | 协议一致性和端到端测试 |
核心依赖原则是:底层库不反向依赖 Relay。Relay 通过 AppState 把具体服务接到 handler 上,避免数据库、搜索或工作流各自启动一套网络入口。
3. Relay 内部结构
Relay 的核心不是一个巨型 handler,而是四类边界:
router.rs / HTTP handlers / WebSocket connection
│
protocol dispatcher
┌───────────┴───────────┐
│ │
EVENT path REQ path
│ │
ingest.rs req.rs
│ │
DB transaction access-scoped SQL/search
│ │
post-commit dispatch historical EVENT/EOSE
│
Redis + local subscription registry + workflowstate.rs::AppState 持有数据库、审计、PubSub、认证、搜索、订阅、工作流、限流器、社区缓存等。它同时启动 Redis 监听、缓存失效和连接控制任务,是进程级协调中心。
4. 多租户不是一个普通字段
社区隔离贯穿所有层:
- HTTP/WS 首先由 host/authority 解析
TenantContext。 - 连接在注册表中携带 community label。
- SQL 查询第一条件优先是
community_id。 - event 主键、频道成员和多数外键都带 community。
- Redis topic 包含 community。
- fan-out 再比较接收连接的 tenant,并执行频道/主体门。
换言之,community_id 不是业务过滤器,而是安全边界坐标。
5. 四条主要数据流
5.1 写入流
客户端签名 → WebSocket/HTTP → auth/scope → crypto verify → tenant/kind/channel checks → DB transaction → durable OK → Redis/local fan-out/workflow。
5.2 读取流
REQ/search/count → parse limits → 构造 community/access scope → SQL/FTS → hydrate → per-event privacy gate → EVENT → EOSE。
5.3 Agent 流
Relay channel event → buzz-acp per-channel queue → ACP stdio → Agent runtime → LLM/tool loop → Buzz CLI/MCP → 签名回复 Relay。
5.4 Git 流
Git credential helper 生成 NIP-98 → Relay 鉴权/授权 → hydrate 临时 bare repo → receive-pack → immutable pack upload → manifest CAS → 提交后发布 Nostr 通知。
6. 源码规模中的复杂度热点
| 热点 | 原因 |
|---|---|
buzz-relay/src/ingest.rs | 大量 kind-specific 约束在统一写入管线交汇 |
buzz-relay/src/req.rs | filter、搜索、计数、历史权限和多类私密 kind 汇合 |
buzz-acp/src/relay.rs / pool.rs | 重连、订阅恢复、每频道串行、跨频道并行、取消与进程生命周期 |
desktop/src-tauri | OS 密钥、sidecar、Git、媒体、Huddle、更新与迁移都在 native shell |
buzz-db | 事件存储同时服务关系投影、线程、反应、工作流、Push 与读副本 |
7. 文档与实现的一处重要偏差
根 ARCHITECTURE.md 的“已知限制”仍提到缺少 rate limiter;当前代码已有 buzz-pubsub::RedisRateLimiter,并在 Relay AppState 构造时接入。反过来,README 把 Push 写在“pending code”一侧,但服务器端 gateway、lease、outbox 和 worker 已相当完整;缺口主要在客户端注册/部署闭环。
这说明必须把“能力基础设施完成”与“最终用户闭环完成”分开判断。
8. 源码入口
Cargo.toml:workspace 成员与公共依赖。crates/buzz-relay/src/main.rs:进程入口。crates/buzz-relay/src/router.rs:HTTP/WS 路由面。crates/buzz-relay/src/state.rs:AppState和后台任务接线。crates/buzz-core/src/tenant.rs:服务器解析的租户上下文。desktop/src-tauri/src/lib.rs:Desktop native command 注册与运行时装配。