Files
buzz/desktop
Will Pfleger fba8a7a94f feat(relay): log WebSocket EVENT writes on the access target (#9154)
Logs every WebSocket `EVENT` on the access target
(`buzz_relay::access`). Before this, accepted writes logged only `Event
ingested` on the handler target, and refused or ephemeral writes logged
nothing.

### What's logged
Each `EVENT` frame writes one `event=write` line when its handler
finishes. The line has `conn_id`, `community`, `pubkey` (the
authenticated login, if any), `kind`, `event_id`, and
`outcome`/`reason`, taken from the OK the relay sent:
- `accepted`
- `rejected` (INFO), with `reason` set to the OK's NIP-01 prefix
(`invalid`, `restricted`, `auth-required`, `duplicate`, `rate-limited`,
…). Any other message is logged as `other`.
- `error` (WARN), when the OK starts with `error`
- `aborted`, when the handler ended before deciding an OK

`outcome` is always the relay's decision. If the OK couldn't be queued
because the outbound channel was full or closed, the line adds
`ok_queued=false`; the field is left off otherwise.

`EVENT`s refused before the handler runs are logged too, where their OK
is sent: admission rate limits, with admission's reason, and a full
handler pool, as `rate-limited`.

The OK text after the prefix, the event's content and its tag values are
never logged. Lines join to `auth`/`close` lines (and so to `peer_addr`)
through `conn_id`, the same way `req` lines do.

Rejected writes are capped per connection by the same refusal-budget
mechanism as refused reads, on their own counter: the first 16
rejections are logged and the rest are only counted, in a new
`writes_suppressed` field on the `close` line. Accepted writes are never
capped.

### How
`access::WriteLog` sends the OK and records it in one call
(`write.ok(...)`). That call replaces every
`conn.send(RelayMessage::ok(...))` in `handle_event` and the
observer-frame handler, so the line always shows what the client was
told.

### Tests
- `access::tests`: the reason comes from the OK prefix only; each
outcome logs at the right level and without content; rejected lines are
capped by the budget and accepted ones are not (draining the channel so
every OK is queued); an OK refused by a full or a closed outbound
channel keeps its outcome and adds `ok_queued=false`.
- `handlers::event::tests::fanout_access`: an unauthenticated `EVENT`
going through `handle_event` writes one `rejected`/`auth-required` line,
with no content or tag values.

---------

Signed-off-by: Will Pfleger <wpfleger@block.xyz>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-11-06 00:46:24 +00:00
..
2026-03-09 13:02:11 -07:00
2026-03-09 13:02:11 -07:00

Buzz

Important

This is the deprecated Buzz 0.X desktop app. Buzz 1.0 lives in block/buzz-app. Build new desktop features there. Change this directory only to fix a 0.X bug, or to keep it compiling after a shared crate change.

Desktop chat shell with:

  • Tauri + React + TypeScript + Vite
  • Tailwind CSS
  • shadcn/ui-ready shared components
  • Biome (lint/format/check)
  • Feature-driven frontend structure

Scripts

  • pnpm dev - run the web frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm format - Biome format (write)
  • pnpm check - Biome check

Structure

  • src/shared - reusable app-wide code (ui, lib, styles)
  • src/features - feature modules (vertical slices)
  • src/app - top-level app composition

Required-community guidance in the legacy app

The legacy desktop reads public NIP-11 metadata before each WebSocket connection. Only requires_nip_fi: true shows the upgrade card. Missing/false requirements keep the existing connection flow. Discovery failures retain an unknown-policy state and continue the existing socket/authentication path; the relay enforces admission. Query/fragment URLs keep their existing socket behavior; the native discovery reader rejects them before making an HTTP request. Credentials never reach a fallback dial. Only explicit required policy opens the upgrade modal. Switching communities invalidates pending checks. The card does not reset keys or remove saved communities.

The upgrade card directs public users to the fixed https://buzz.xyz URL to download an up-to-date Buzz client on every supported desktop platform and for every required community. If the browser cannot open, the card shows the public URL for manual navigation. Discovery never supplies a trusted download or sign-in origin.