What an Event Becomes Inside Buzz

Buzz's central mechanism is not simply that it stores messages; it turns a signed event into a set of bounded consequences. This chapter follows that path—from connection and authentication through verification, storage, delivery, search, audit, and workflow evaluation—so readers can see where each guarantee is established and why some signals are deliberately not durable.

The result is a more useful question than “does Buzz have chat?”: when a human or agent submits one action, what does the relay accept, what does it preserve, and what does it pass on?

A small envelope carries a large vocabulary

Buzz uses the Nostr NIP-01 event format as its basic unit. An event contains an identifier derived from a canonical serialization, the public key of the signer, an integer called kind, a set of tags, content, and a Schnorr signature. The shape is small enough that a client does not need a new transport protocol every time the workspace gains a new capability.

The kind is the dispatch switch. A client can subscribe to certain kinds; the relay can decide how to validate, store, route, or interpret them; and a new feature can occupy a new kind while preserving the surrounding envelope. Standard Nostr kinds are used where they already express the intended behavior, such as reactions or group concepts. Buzz adds custom kinds for capabilities that have no established Nostr equivalent, including workflow and job-related activity.

This arrangement separates representation from meaning. The event envelope says who signed something and what structured data it carries. The kind and tags give the relay enough information to decide what the event is about. A channel message, a reaction, a workflow transition, and a repository-related event can therefore travel through the same relay without being the same kind of object to the reader.

That distinction is important for composability. If a message and a workflow result were created by unrelated systems, connecting them would require a cross-system identifier, an integration service, and agreement about who may see the link. In Buzz, the relationship can be expressed through event tags, channel context, and a common relay. The shared envelope does not solve every application problem, but it gives those problems a common place to be solved.

The relay is authoritative because it is the point through which clients connect, authenticate, submit events, and request history. The architecture explicitly rejects a peer-to-peer event exchange or gossip model for the current design. Clients connect to one relay; that relay verifies signatures, persists accepted events, sends them to eligible subscribers, and coordinates the other projections. A desktop client is therefore a view of the workspace, not the workspace's only memory. An agent using the CLI or an external Nostr client can participate through the same boundary.

The connection establishes the first boundary

An event cannot be interpreted safely before the relay knows who is connecting and which workspace the connection belongs to. The documented connection lifecycle begins by binding the connection to its community or rejecting an unknown host in the multi-community design. It then limits connection capacity, sends a NIP-42 authentication challenge, and requires the client to authenticate before submitting events or creating subscriptions.

The challenge-response step is more than a login screen. It binds a live connection to a public key that can later be compared with the key inside an event. The relay maintains connection state, runs a receive path for incoming frames, a send path for outbound frames, and a heartbeat path for liveness. When the connection closes, subscriptions and send channels are removed and capacity is released. These transitions matter because a relay is not only a database; it is also a live delivery system with resources that must be reclaimed.

HTTP clients use a corresponding signed-request path rather than a WebSocket challenge. The exact transport differs, but the architectural rule is the same: the relay must establish an authenticated principal before it treats an event as an instruction. A signature on an event is not a substitute for authenticating the connection that submitted it. The two checks answer related but different questions: does this key sign the event, and is this key currently allowed to submit it through this interface?

The community boundary adds another distinction. In a single-relay deployment, the relay URL naturally selects one workspace. In the repository's intended multi-community model, the host is resolved before request handling and client-supplied tags cannot override it. A channel tag can identify a channel, but it is not allowed to become an unverified tenant selector. This is a design boundary that will matter later when identity and authorization are examined directly.

Acceptance is an ordered pipeline

Once the connection is authenticated, Buzz's current ingest seam performs checks in an order that reveals the system's trust model. The relay first refuses categories that must never enter ordinary storage, such as authentication events submitted as user content and relay-only membership notifications. It also rejects transport-inappropriate events, such as certain WebSocket-only kinds submitted through HTTP.

The event is then verified. The relay checks the signature and the event identifier, using a blocking task for the CPU-bound cryptographic work. It checks that the timestamp is within the allowed drift and that content is within the configured size limit. Except for the special gift-wrap case, the event's public key must match the authenticated identity. At this point Buzz has evidence that the event is structurally valid and was signed by the principal claiming to submit it. It still has not established that the principal may perform this particular action.

Next comes authorization. The relay determines what scope the event kind requires and checks that the authenticated context carries it. Channel-related events are subject to channel membership and visibility rules. A valid signature does not let an agent write into a private room it has not joined, just as a human key does not bypass the relay's membership checks. Command-like event kinds are routed only after signature, timestamp, identity, and scope validation; they are not privileged merely because their numeric kind tells the relay what they intend to do.

The order is consequential. If routing happened before authentication, a command handler could become an alternate security boundary. If storage happened before signature verification, the database would contain claims the relay had not established. If access checks happened only during live delivery, a historical query or search path could become a leak. Buzz's architecture puts the gate before the write and describes additional authorization checks at subscription and delivery boundaries.

sequenceDiagram participant C as Client participant A as Auth boundary participant R as Relay ingest participant D as Postgres event store participant F as Fan-out participant S as Search projection participant L as Audit chain participant W as Workflow engine C->>A: Connect and answer challenge A-->>C: Authenticated context C->>R: Submit signed event R->>R: Verify ID, signature, time, size, scope alt Persistent accepted event R->>D: Idempotent insert R->>F: Deliver to authorized subscribers R->>S: Update searchable projection R->>L: Append audit entry R->>W: Evaluate workflow triggers R-->>C: Acceptance result else Ephemeral event R->>R: Verify and check channel access R->>F: Fan out without durable insert R-->>C: Transient result end

The diagram shows two paths rather than one. Most of Buzz's collaboration record is intended to be persistent, but the relay also carries presence and typing signals whose usefulness depends on immediacy rather than historical retention.

One write creates several projections

For a persistent event, the relay's work continues after validation and authorization. It inserts the event into Postgres using idempotent behavior: if the same event is submitted again, the database can recognize the existing record rather than creating a duplicate canonical event. This is an important protection for reconnecting clients and retrying senders. It does not mean every consequence of the event happens exactly once.

The event may be published through Redis when it is channel-scoped, then fanned out to matching local WebSocket connections. The relay also makes the event available to search, records an audit action, and evaluates workflows. These stages have different owners and different failure modes. The database row is the canonical stored event. Fan-out is a delivery concern. Search is a derived view. Audit is a tamper-evident record of selected actions. Workflow evaluation is a transition into further work.

That separation is what makes the event log useful and what keeps it from becoming magical. A successful insert can coexist with a delayed subscriber, a search projection that has not yet been consulted, or a workflow action that later fails. If a workflow sends a message, that new message is another event with its own validation and authorization path; it is not simply an invisible side effect hidden inside the original record. Conversely, a search hit does not grant permission to reveal the event. The relay must reauthorize candidates before returning them.

The architecture describes audit and workflow triggers as asynchronous or otherwise non-blocking side effects, while the current search implementation derives its full-text vector as part of the event row rather than maintaining a separate indexer. That split protects acceptance from making downstream automation a prerequisite while keeping search close to canonical storage. It still means that “accepted” and “all projections and side effects are settled” are different states: audit or workflow consequences may lag or fail independently even when the event is searchable. A reader who wants a reliable operational history needs to know which record is authoritative and which views may lag or fail independently.

The same principle applies to references between events. A reaction, reply, approval, or workflow result can point to another event, but the relay still has to resolve that reference in the right channel and community and apply the relevant access rules. A shared identifier is useful only when scope is preserved around it.

Why ephemeral events are intentionally absent

Presence and typing indicators follow a different path. Buzz reserves an ephemeral range for events that should not be stored in Postgres, searched, or placed in the audit chain. A presence update can update Redis-backed presence state and be fanned out to local subscribers. Other transient signals can be verified, checked for channel membership, published through Redis, and delivered without becoming historical records.

This is not an inconsistency in the event model. It is a classification decision about what the workspace needs to remember. A message such as “the deployment is complete” is useful as a durable fact that can be searched later. A typing indicator is useful only while someone is composing. Recording every heartbeat would turn a collaboration history into infrastructure noise and would make the meaning of the event log less clear, not more complete.

The boundary does create a trade-off. A future reader cannot reconstruct every transient state from the durable log, and a missed presence update is not repaired by a historical query. The relay's live connection and pub/sub paths therefore have their own liveness and recovery concerns. A workspace that promises durable decisions but treats transient signals as disposable needs to make that distinction visible to users.

The same reasoning explains why an event log should not be confused with a complete transcript of reality. It records accepted durable assertions and selected audit actions. It can provide provenance for what was submitted, who signed it, and how the relay handled it. It cannot establish that an agent's conclusion was correct, that a human saw every live notification, or that a transient signal existed after it expired.

The pipeline's real output is a bounded record

By the end of ingestion, a persistent Buzz event has become more than a row and less than a guarantee of truth. It has passed through an authenticated boundary, cryptographic verification, scope checks, and a durable write. It may then appear to authorized subscribers, become searchable, enter an audit chain, and trigger further workflow evaluation. Each result inherits the event's identity and context but serves a different operational purpose.

That is the relay-centered bargain. Buzz concentrates coordination so that a message, a code change, an agent action, and a workflow result can remain related. In exchange, the relay must own the ordering of checks, the separation of projections, the limits of live delivery, and the difference between durable and ephemeral state. The next problem is therefore not simply whether an event is valid. It is whose event it is, which room it belongs to, and what authority that identity has inside the workspace.

References