Commit Graph

25 Commits

Author SHA1 Message Date
Mic Neale
4544ba1713 chore(mesh): upgrade MeshLLM to 0.76.2 (#7559)
## Summary

Upgrade Buzz from MeshLLM `v0.76.0-rc9` to the latest stable [v0.76.2
release](https://github.com/Mesh-LLM/mesh-llm/releases/tag/v0.76.2) (via
v0.76.1).

- Update all eight Mesh git dependencies across desktop and relay smoke
examples; both lockfiles resolve all 47 Mesh packages to
`a0c1e66b0ac037dd56544b9e2d94969ea43d694f` (tag `v0.76.2`). All non-Mesh
lock records are unchanged by the 0.76.1 → 0.76.2 bump.
- Match Mesh's `ed25519-dalek = 3.0.0` and `rusqlite = 0.40`
dependencies.
- Explicitly enable rusqlite's `fallible_uint` feature, preserving
Buzz's existing `u64` SQL conversions when **mesh is disabled**.
Mesh-enabled builds previously supplied this transitively, so testing
both configurations matters.
- Temporarily pin **only** the optional `sqlx-sqlite` package to the
merged upstream compatibility fix
[transact-rs/sqlx#4402](https://github.com/transact-rs/sqlx/pull/4402),
revision `94aafe3a68884d923b0798a767c8d7f6cfda89d2`. SQLx 0.9.0 caps
`libsqlite3-sys` below 0.38, while Mesh 0.76 requires 0.38. Cargo
resolves the conflict even with SQLite disabled. The fix raises that
upper bound; remove the patch once released. Buzz's active PostgreSQL
driver stays on crates.io SQLx 0.9.0.
- Preserve the explicit Linux keyring 3 `crypto-rust` feature so Secret
Service sessions retain DH encryption independently of Mesh keyring 4.
- Preserve the dedicated examples-only `buzz-mesh-smoke` crate and
lifecycle workflow wiring, keeping Mesh/native-runtime dev dependencies
out of relay CI builds.
- v0.76.1 → v0.76.2 upstream delta: self-updater fix for composed
product-v2 bundles (Mesh-LLM/mesh-llm#1844) plus release plumbing — no
API changes affecting Buzz.
- Merged `origin/main` (`7c789dee0`) without rewriting shared PR
history.

### Validation at `ae4adba15` (local macOS ARM64, Hermit toolchain)

- **Passed:** `cargo test --locked -p buzz-mesh-smoke --all-targets`
(all six example harnesses compile; no live harness execution).
- **Passed:** desktop Tauri workspace tests, both default and
`--features mesh-llm` graphs (3,296 tests with mesh enabled, 0
failures).
- **Passed:** `just desktop-tauri-clippy` (both feature graphs, `-D
warnings`), root workspace clippy `-D warnings`, `cargo fmt --all
--check`.
- **Passed:** `--locked` metadata resolution for both workspaces;
lockfile diff audited to touch only Mesh package records.
- **Passed:** full pre-push hook suite on the final push (branch-skew,
rust-tests, desktop-tauri-checks, file-size-check) — no hooks bypassed.
- **Not run:** live Mesh inference/admission smoke or installed-app UI
exercise. CI lifecycle smoke coverage applies.

Originating Buzz conversation:
buzz://message?channel=dffbc117-845a-4c02-bc3f-eaeeefc4deaa&id=670f9c262e1ec0a4df5600b3173a0c5de2abe17e08ba9ccfdd8eff109fadf1a8

---------

Signed-off-by: Thinker <75d8a808fa21bb8d1812e080cf471db601c6e8e6a62dcd516d37531e83a7bb77@meshllm.communities.buzz.xyz>
Signed-off-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Thinker <75d8a808fa21bb8d1812e080cf471db601c6e8e6a62dcd516d37531e83a7bb77@meshllm.communities.buzz.xyz>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Galadriel <b81c841ed20a8e17caf4e6fac2f6f3bc61d304c84b8394720f6d00f37538c47e@meshllm.communities.buzz.xyz>
Co-authored-by: Gu <gu@buzz>
2026-09-24 07:32:07 -06:00
Mic Neale
44316ff72f feat(mesh): upgrade to mesh-llm 0.76.0-rc8 and recommend Qwen3.8 27B (#6189)
Upgrades Buzz's mesh-llm dependencies through the released `v0.76.0-rc8`
tag (`2040765d`), including the Qwen3.8 curated recommendation and rc8's
scheduler/runtime improvements.

**Scope note:** the earlier open-relay/unenforced-admission mode has
been removed from this PR at Mic's direction — it is not a product mode
we want. Mesh admission remains roster/allowlist driven, exactly as on
`main`: on a relay with no NIP-43 membership snapshot the mesh runs
self-only. No NIP-11 mode probing, no mode-transition restarts. A future
perimeter/admission strategy for open relays will be designed
separately.

This PR also:
- seeds `BUZZ_AGENT_LLM_TIMEOUT_SECS=660` for mesh agents, above
MeshLLM's 600-second backend timeout;
- makes `desktop-tauri-clippy` lint both default and `mesh-llm` cfg
graphs;
- runs the feature-enabled desktop test suite in CI;
- recommends Qwen3.8 27B Q4_K_M for 64 GB-and-larger machines, then
ladders down through Gemma 4 E4B and Qwen 9B for smaller machines;
- keeps stored shared-compute `auto` translated to MeshLLM's supported
wire model `mesh`.

RC8 verification:
- `just ci` passed locally at
`92ecc7ec933bdd4df804cc9f28a2b51efa5313c5`.
- Pre-push differential gates passed, including both desktop Tauri cfg
graphs and package tests.
- A prior isolated runtime smoke used the RC8 binary's OpenAI endpoint
for a Buzz-shaped system/user/tool/tool-result/final-response loop; all
assertions passed and the isolated process was shut down.

Perf previously measured on M5 Metal, Qwen3.8-27B-Q4_K_M: TTFT 0.22–0.32
s, ~25 tok/s streaming; agent-shaped turns ~1 s to first token after the
first (prefix cache).

---------

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Signed-off-by: Jimmy <1fe240cd1a8cf775f6f3060f115e5a303181f3abf28ad4cb0c2515f4a02b36a8@meshllm.communities.buzz.xyz>
Signed-off-by: Alessandro Joabar <sandro@squareup.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Jimmy <1fe240cd1a8cf775f6f3060f115e5a303181f3abf28ad4cb0c2515f4a02b36a8@meshllm.communities.buzz.xyz>
Co-authored-by: Mic Neale <305999590+micspiral@users.noreply.github.com>
Co-authored-by: Alessandro Joabar <sandro@squareup.com>
2026-09-08 07:30:45 -07:00
Kalvin C
8a2c9af2db feat(deletion): add durable whole-community deletion (#4425)
## Summary

Adds a durable, operator-controlled V1 for deleting an entire Buzz
community without deleting another tenant's data.

The workflow is exposed through `buzz-admin deletions`:

- `sweep` records independent fleet storage-taxonomy observations
- `submit`, `list`, `inspect`, and `approve` manage a deletion request
- `unblock` resumes a fail-closed request after an operator records
remediation identity and reason
- `run` and `drain` execute bounded work

Requests advance through a PostgreSQL-backed state machine and stop at
`retention_pending` after logical deletion has been independently
verified across PostgreSQL, object storage, and Redis.

This PR ships the engine and CLI, not a continuously running worker or
Kubernetes packaging. For V1, a cluster/VM administrator invokes
`/usr/local/bin/buzz-admin` from the existing relay image, for example
with `kubectl exec` or an equivalent container/VM exec path.

## What whole-community V1 removes

For the target community, V1 removes:

- rows from the allowlisted community-scoped PostgreSQL catalog,
including members, profiles, authored events and bodies, DMs, reactions,
mentions, memberships, tokens, workflows, moderation, audit, feedback,
and rate-limit state
- media sidecars and upload-attribution records under
`_meta/<community>/` and `_uploads/<community>/`
- Git repository pointers under `repos/<community>/`
- Redis keys under `buzz:<community>:*`

The community row survives as a permanent tombstone, and deletion
control-plane records remain as evidence of the request, approval,
execution, and result.

## Safety model

Deletion is not a broad `DELETE CASCADE` followed by optimistic cleanup.
The destructive boundaries are durable and fail closed.

### 1. Inventory and approval

- `submit` resolves the target and freezes the schema plus summary-only
storage inventory.
- Approval is bound to the exact request, community, and frozen
inventory digest.
- Unsupported manifest versions, malformed keys inside the target's
owned prefixes, live scoped-table/write-fence coverage drift,
frozen-inventory mismatch, and approval mismatch block execution rather
than guessing. Migration and catalog revision numbers are not
authorization gates; the executor validates the live safety shape
instead.
- Storage inventory is server-side prefix scoped to exactly:
  - `_meta/<community>/`
  - `_uploads/<community>/`
  - `repos/<community>/`
- The deletion path never lists the whole shared bucket and has no
arbitrary per-community object cap. Its listing work is proportional to
the target community's bindings, not total fleet storage.
- Fleet-wide taxonomy sweeps remain independent observability. They
report unknown writer shapes but do not gate deletion submission,
fencing, or destructive progress. Maintainers must add deletion taxonomy
coverage whenever a new community-owned object-key class is introduced;
writer-coverage tests bind the current media and Git writers to that
contract.

### 2. Quiesce, fence, and destructive freeze

- Writes continue through submission, inventory, and approval. They stop
when execution moves the target into `quiescing` and then establishes
the durable fence.
- Already-admitted external effects finish under heartbeated
serving-write leases; the exact admitted lease may renew while the
community is quiescing, but new lease acquisition is rejected. The
executor drains admitted leases before destructive work.
- Invite minting after quiescing begins fails as typed `AccessDenied`
(HTTP 503 at the relay boundary) before an invite can be persisted.
- Database triggers enforce the community write fence across the
complete catalog of community-scoped tables. Startup/readiness and
destructive execution validate that catalog so a newly added but
unfenced table cannot silently escape.
- **Named isolation assumption — fresh write snapshot.** Every writer
transaction that can reach a community-fenced relation must use
PostgreSQL `READ COMMITTED`; each guarded write therefore observes a
statement snapshot no older than acquisition of the community deletion
lock. `REPEATABLE READ` and `SERIALIZABLE` can retain a pre-fence
snapshot and are unsupported for writers. The writer pool refuses
non-`READ COMMITTED` sessions at connection setup, and both SQL fence
functions reject an explicit per-transaction isolation override with
SQLSTATE `25000`. Configuration-delivered bad isolation can surface
through SQLx as a pool-acquire timeout because every `after_connect`
attempt is rejected; the precise `community writes require READ
COMMITTED isolation` reason remains observable when the SQL guard is
reached. Read-only replica transactions are outside this assumption.
- Holding the shared advisory lock until the guarded write executes is a
separate liveness condition: under `READ COMMITTED`, releasing it early
does not permit resurrection because the trigger rechecks the fence, but
it can turn a fleet sweep into a statement-wide SQLSTATE `55000` abort.
- After the fence closes writers, storage is re-enumerated into chunked
side-table rows. Per-prefix counts and digests bind those concrete keys
to the destructive manifest.
- Manifest chunk insertion, update, and deletion are protected after
freeze. This closes the race where an unbound key could otherwise appear
after the manifest was committed.

### 3. Checkpointed destruction

- Target-owned object bindings are deleted from the frozen destructive
manifest in bounded batches with durable progress.
- The concrete key list lives in chunked side-table rows rather than one
request-row JSON value. It supports large communities, resumable
execution, and terminal cleanup.
- Missing objects are accepted as idempotent crash-window outcomes;
malformed ownership, changed evidence, and unexplained target-prefix
drift fail closed.
- PostgreSQL purging remains scoped by `community_id`, including the
guarded NIP-RS hard-delete path discovered with real Desktop kind
`30078` read-state data.
- Redis cleanup explicitly scans and `UNLINK`s only
`buzz:<community_id>:*`. Natural expiry is insufficient because some
keys, including tunnel generation counters used as fencing state, are
deliberately persistent.

### 4. Independent verification

- PostgreSQL logical absence is checked after purge.
- The three target-owned storage prefixes are freshly inventoried again
and must be empty.
- Redis requires two complete empty namespace scans.
- Only after all three stores pass does the request advance through
`logically_verified` to `retention_pending`.

## What V1 deliberately does not erase

### Shared content-addressed storage

Per-community deletion removes bindings, metadata, attribution records,
and Git pointers. It does **not** physically delete fleet-shared CAS
bytes that another community may still reference:

- media blobs and thumbnails
- Git manifests, packs, and indexes (`manifests/`, `packs/`, and `idx/`)

Safe reclamation requires a separate fleet-wide reachability and
retention GC. Unknown keys elsewhere in the shared bucket do not block
one community's deletion; malformed or unrecognized keys inside that
community's three owned prefixes still fail closed.

### External retained copies

The online logical-deletion proof does not erase object
versions/replicas, database backups/WAL, CDN copies, provider retention
copies, or observability exports. Those require their own retention and
purge controls.

### Member-only erasure

This PR erases a whole community. It does not implement the different
operation "erase one npub while preserving the community."

Removing membership or accepting NIP-09 is not member erasure. A
member-only workflow would need to find and selectively remove or redact
authored event content and pubkeys, profile data, DMs, reactions,
mentions, memberships/roles, tokens, workflows/subscriptions, upload
attribution, moderation/audit history, repository attribution, and
identity embedded in tags or JSON. It would also need explicit rules for
ownership transfer, surviving replies and thread metadata, audit-chain
integrity, immutable Git history, and shared-CAS reachability. That
requires a pubkey-level fence and selective graph rewrite; it is a
separate deletion product, not a safe extension of this whole-tenant
worker.

## In scope

- migration `0029_community_deletion.sql`: requests, approvals, leases,
manifest chunks, checkpoints, tombstones, and the universal write-fence
catalog
- durable executor leases, generations, heartbeats, retry/block state,
and resumable stage transitions
- operator-driven `sweep`, `submit`, `list`, `inspect`, `approve`,
`unblock`, `run`, and `drain` commands
- serving-path fences for database writes and external effects across
event ingest, media, Git, workflow, push, invites, mesh/tunnel, and
related paths
- target-prefix-only storage inventory, summary manifests, post-fence
destructive chunks, and bounded batch deletion
- exact community Redis namespace purge and two-pass absence
verification
- cross-community isolation, crash/resume, manifest-integrity,
writer-taxonomy, and schema/migration regressions
- desired-state `schema/schema.sql` support without requiring a SQLx
migration ledger

## Deferred / not covered

- dedicated Helm/chart worker Deployment, service account, secrets,
probes, resources, and network policy
- autonomous `buzz-admin deletions worker` poll loop and worker-only
health server
- least-privilege separation among migration, relay-serving, and
destructive execution roles
- fleet-wide shared-CAS physical GC
- backup/provider/CDN/observability retention completion
- member-only erasure
- provider-native conditional-delete improvements
- a general force-continue escape hatch; permanent safety failures
remain fail closed unless an operator remediates the cause and records
an audited `unblock`

The removed continuous-worker implementation remains deferred; no remote
follow-up branch is claimed by this PR.

## Validation

### Current PR head and repository state

Current pushed head: `359d8402ee15f049768f54156f67b953c7a7e2ed`, rebased
onto `cc9a2f783375e51a6e8d1f2f9d01d5f7e22813d1` (`origin/main` at push
time). The complete PR diff is now 47 files, 9,834 additions, and 517
deletions.

The bespoke source-scanner stack was removed to keep this PR scoped to
community deletion. Tyler/team requested the underlying fenced-write
safety behavior, not `ast-grep`,
`crates/buzz-db/tests/community_fenced_writes.rs`, its 27 fixtures, or
the new `scripts/lints/community_*.yml` rules. Those scanner-specific
files, dependencies, Hermit links, and runner wiring are absent from the
current tree. The production database write fence, startup/destructive
live-catalog validation, and deletion behavior remain.

Source validation on this exact SHA passed:

- `cargo fmt --all -- --check`
- `bash -n scripts/run-tests.sh`
- `cargo nextest run -p buzz-db --all-targets`: 102 passed, 173 skipped,
0 failed
- `cargo nextest run -p buzz-deletion --all-targets`: 10 passed, 9
skipped, 0 failed
- `cargo nextest run -p buzz-admin --all-targets`: 1 passed, 0 failed
- affected-package/all-target Clippy with warnings denied
- lockfile consistency
- Helm 3.16.4 lint and all 44 chart unit tests
- Helm region controls using that fixture: default
`BUZZ_S3_REGION=us-east-1`, explicit `eu-west-2` override, and
blank-region schema rejection

The prior Kubernetes battery below was run against
`928992237358a3294621ac0280830b77155abc04`. It remains useful evidence
for the patch-equivalent production deletion implementation, but it is
**not** claimed as exact-SHA evidence for current head
`359d8402ee15f049768f54156f67b953c7a7e2ed`; the current cleanup removes
only scanner/test/tooling infrastructure. CI restarted for the new head
after the rebase and is pending. Human review remains
`CHANGES_REQUESTED`.

### Prior-head live Kubernetes deletion and safety gates

The full program used one immutable image, real PostgreSQL, Redis,
MinIO, and a three-relay Kubernetes release:

- source: `928992237358a3294621ac0280830b77155abc04` (**prior head**)
- image: `buzz-e2e:sha-928992237358`
- immutable image digest:
`sha256:a1a204f4618ac22d9e210be5e5290645a15d79831ae30b0e44379357c8e4a895`
- evidence root:
`/tmp/buzz-e2e/20260807T033025Z-928992237358-full-gates/`
- evidence-manifest digest:
`82875c5bc9bea7370b796a7aef3457b3a1c8306c84c59e0f7388bbb5ad30e865`

Passed gates at that prior head:

- **Chart/operator region:** default `us-east-1`, explicit nondefault
propagation, blank-region schema rejection, live in-pod environment, and
an in-pod taxonomy sweep over 18 objects with zero unknown.
- **Fenced writers and lifecycle:** open-write/fence ordering;
100-attempt anti-starvation; invite, push matcher, and exhausted-reaper
bystander isolation; non-`READ-COMMITTED` rejection; manifest/tombstone
contracts; eight-failure stage block and audited `unblock`.
- **Destructive lifecycle:** submit → approve → run →
`retention_pending`; PostgreSQL tombstone and Redis/S3 verification
true; zero retries/errors; terminal reruns rejected with exit 5.
- **Fresh 10,001-object crash boundary:** exactly two chunks (10,000 +
1). The executor deleted chunk 0 from MinIO while its PostgreSQL stamp
was row-lock-blocked, was killed with `SIGKILL`, left one object and
both stamps absent, then resumed the same request under generation 2 to
zero objects and terminal state.
- **Independent dead-owner recovery:** a dedicated executor claimed
generation 1, blocked before effects, and was killed through containerd
with `SIGKILL` (no TERM cleanup). The request remained owned and
unreclaimable before lease expiry; a successor claimed generation 2
after 60 seconds and completed with two attempts and zero retries.
- **Three-pod socket isolation:** ordinary NIP-42 and joined
huddle-audio target witnesses on every replica received exact `1008 /
community deleted`; healthy-tenant witnesses on those pods remained
live; deleted-host reconnect returned HTTP 404.
- **Health/provenance:** all replicas independently returned ready and
retained the exact image digest before/after destructive runs and an
audio-enabled rolling restart; PostgreSQL, Redis, and MinIO were healthy
at close.

Instrument corrections were retained as evidence rather than counted as
product failures: a foreground PostgreSQL forward caused an initial
`PoolTimedOut`; Kubernetes pod deletion exercised graceful TERM rather
than dead-owner recovery; shell-background socket witnesses died with
their parent; and the first image build hit the corporate TLS proxy.
Detached forwarding/witnesses, containerd `SIGKILL`, and the configured
internal CA/Artifactory mirror produced the discriminating runs without
weakening product security.

### Prior-head cleanup

For the prior-head Kubernetes run, the Helm release was removed,
namespace absence was verified, run-owned Screen sessions were absent,
and that source worktree remained clean. The evidence manifest was
independently recomputed and every indexed artifact passed `shasum -a
256 -c`. The current `359d8402` source worktree is also clean after the
scanner-only cleanup and push.

---------

Signed-off-by: npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc <5288f082d91aff2de5bc8be23fbfa01ca2e3859cac57a91b7a3fa9f12349505c@buzz.block.builderlab.xyz>
Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: am <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
Signed-off-by: cid <d9f92a72922bf45c17379a47d64dae84b6020397c2d5a52b5317d512068cd9d3@buzz.block.builderlab.xyz>
Co-authored-by: npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc <5288f082d91aff2de5bc8be23fbfa01ca2e3859cac57a91b7a3fa9f12349505c@buzz.block.builderlab.xyz>
Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
Co-authored-by: cid <d9f92a72922bf45c17379a47d64dae84b6020397c2d5a52b5317d512068cd9d3@buzz.block.builderlab.xyz>
2026-08-12 09:25:58 -07:00
Dave Grochowski
397796c5f3 feat(tracing): add PostgreSQL tracing spans (#3678)
## Why
Expose PostgreSQL datastore latency within existing request traces so
slow logical database operations can be identified without recording
tenant data or query arguments.

## What
- Add client spans around logical PostgreSQL operations across the
database facade, search, audit, replica fencing, and command persistence
- Use a dedicated `buzz_datastore` target and `db.system.name =
"postgresql"` for filtering and backend classification
- Exclude health-check database calls and scrub raw identifiers and
errors from newly traced paths

## Risk Assessment
Medium — this instruments frequently used datastore paths and increases
trace volume when enabled, but does not change SQL execution or
datastore behavior. Existing OpenTelemetry filtering controls export.

## References
- Pre-push clippy and fast unit-test hooks passed

Generated with Amp

---------

Signed-off-by: David Grochowski <dgrochowski@squareup.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-08-12 08:04:54 +10:00
Mic Neale
240cdd3ea1 chore: mesh upgrade, clean up legacy special case code, simplify model selection for mesh (#5289)
Shared compute now has exactly two model choices: MeshLLM's virtual
`mesh`
model, or a model you name. Buzz picks between them in one place, and
buzz-agent no longer knows meshes exist.

## What changed

- **MeshLLM v0.74.0 → v0.75.1.** v0.75.0 added
`degrade_to_single_model`, so a
  `model=mesh` request is answered by one served model when there is no
committee to form, instead of failing. v0.75.1 adds Mesh-LLM#1196, which
skips stale pre-0.75 runtime cache entries rather than aborting startup
on
them — without it, anyone who had run mesh on 0.73/0.74 could not start.
- **Deleted the client-side mesh catalog probe.** buzz-agent used to
poll
`/v1/models` (5s TTL, 30s cooldown, two-observation debounce) to decide
whether `mesh` was safe to send. MeshLLM now decides per request, so the
  polling, its hysteresis, and its 503 fallback are gone.
- **One mapping point.** `relay_mesh_wire_model()` turns the stored
value into
a wire name: `auto` becomes `mesh`, a named model passes through. The
spawn
env, the ACP harness, and the readiness probe all use it, so they cannot
disagree — previously `BUZZ_ACP_MODEL` and the probe both said `auto`, a
name
  the mesh does not advertise.
- **Removed the `nostr-relay-pool` advisory exception.** #5404 allowed
RUSTSEC-2026-0243 "after mesh-llm migrates to nostr-sdk >= 0.45".
v0.75.1
does, so the retired crate is gone from both lockfiles and the exception
  would only mask a future advisory for it.
- **Deleted `scripts/ensure-mesh-native-runtime.sh`** and its six
justfile call
sites. It built llama.cpp from source into the runtime cache; the app
already
  downloads the signed release runtime itself, and CI never called it.

## Why it is better

**−639 lines of Rust.** Availability is decided by the node that knows
the
answer, per request, instead of by a client cache that could be stale
for up to
30 seconds. A second worker joining now takes effect on the next request
rather
than after two confirming probes.

## Behaviour change

A 503 on an explicit `mesh` request takes the ordinary transport retry
under
the same model instead of failing over to a second one — there is no
second
model to fail over to now. MoA repairs partial committee results
internally
before it reaches that point.

## Validation

`crates/buzz-relay/examples/mesh_agent_e2e.rs` now sends `mesh` where it
previously sent `auto` or the physical model id, so no leg was covering
what
Buzz actually puts on the wire. 4/4 on gemma-4-E4B, gemma-4-26B-A4B, and
Qwen3-8B — including a real ACP tool call through `mesh` into
buzz-dev-mcp,
asserted by reading the written file back off disk.

Hand-tested in the desktop app on both gemma-4 sizes: picked Auto, agent
logged
`model_id=mesh`, replied in channel.

## Not covered

A committee that forms and then loses a worker returns 502, and that
needs two
workers to reproduce — not testable on one machine.

---------

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
2026-08-11 11:40:07 -04:00
Will Pfleger
6e5c462ac5 chore(release): release Buzz Relay version 0.2.1 (#2856)
## Buzz Relay release v0.2.1

### Changes since relay-v0.2.0:

- fix(sdk): preserve self-mention p tags in message and forum event
builders ([#4975](https://github.com/block/buzz/pull/4975))
([`78c87ae20e`](78c87ae20e))
- feat(desktop): adding rich link previews to messages
([#3818](https://github.com/block/buzz/pull/3818))
([`1922d49cb2`](1922d49cb2))
- feat(relay): accept kind:30179 private managed-agent events at ingest
([#5133](https://github.com/block/buzz/pull/5133))
([`ad923353a2`](ad923353a2))
- fix(media): require authenticated reads
([#4610](https://github.com/block/buzz/pull/4610))
([`769ac70b74`](769ac70b74))
- feat(identity): recover desktop identity from a signed-in phone
([#4845](https://github.com/block/buzz/pull/4845))
([`6eb65919f1`](6eb65919f1))
- ci: prove the relay-driven mesh lifecycle — discover, join, infer,
deny — with real nodes
([#3862](https://github.com/block/buzz/pull/3862))
([`38bf642fcf`](38bf642fcf))
- relay: fuzz WebSocket 1012 restart-close timing on graceful drain
(BUZZ_DRAIN_JITTER_MS)
([#4542](https://github.com/block/buzz/pull/4542))
([`e14fff74d0`](e14fff74d0))
- fix(reactions): support max-length custom emoji
([#3833](https://github.com/block/buzz/pull/3833))
([`2ea9385015`](2ea9385015))
- fix(channels): restrict private-channel invitations
([#4612](https://github.com/block/buzz/pull/4612))
([`efe1893dd3`](efe1893dd3))
- fix(workflow): bind trigger author to the signed event
([#4607](https://github.com/block/buzz/pull/4607))
([`885bed35ee`](885bed35ee))
- fix(git): revoke access for banned relay members
([#4608](https://github.com/block/buzz/pull/4608))
([`997b8caaa4`](997b8caaa4))
- Define private managed agent wire protocol
([#4593](https://github.com/block/buzz/pull/4593))
([`067c085f37`](067c085f37))
- perf(relay): index channel-id lookups and skip trace-only reads
([#4647](https://github.com/block/buzz/pull/4647))
([`bc9e6528a7`](bc9e6528a7))
- Polish mobile inbox and media flows
([#4512](https://github.com/block/buzz/pull/4512))
([`feccf4eabc`](feccf4eabc))
- fix(git): allow deleting the default branch
([#4297](https://github.com/block/buzz/pull/4297))
([`fc598f5f8d`](fc598f5f8d))
- feat(projects): add buzz projects CLI commands (NIP-MP kind:30621)
([#4020](https://github.com/block/buzz/pull/4020))
([`b7bb15122e`](b7bb15122e))
- perf(relay): serve relay-membership checks from the read replica
([#4124](https://github.com/block/buzz/pull/4124))
([`ac4fa13b8e`](ac4fa13b8e))
- fix(relay): allow open relays to set their NIP-11 workspace icon
(kind:9033) ([#3998](https://github.com/block/buzz/pull/3998))
([`5765fc74b7`](5765fc74b7))
- feat(relay): accept kind:30621 multi-repo projects at ingest
([#3171](https://github.com/block/buzz/pull/3171))
([`cb9701cd30`](cb9701cd30))
- feat(relay): raise hosted community limit to five
([#3829](https://github.com/block/buzz/pull/3829))
([`10d5a26414`](10d5a26414))
- fix(relay): align NIP-11 max_limit with REQ ceiling
([#3635](https://github.com/block/buzz/pull/3635))
([`23f0c26b1c`](23f0c26b1c))
- feat(relay): gate kind 30178 team-catalog reads behind the shared tag
([#3358](https://github.com/block/buzz/pull/3358))
([`114d40d9d3`](114d40d9d3))
- fix(db): isolate usage metrics advisory-lock test on scratch DB
([#3670](https://github.com/block/buzz/pull/3670))
([`dba97eecd9`](dba97eecd9))
- perf(presence): reduce heartbeat frequency
([#3783](https://github.com/block/buzz/pull/3783))
([`bf139e8d0b`](bf139e8d0b))
- feat(mesh): upgrade embedded mesh to v0.74 and harden shared compute
(split 1/2 of #3467) ([#3741](https://github.com/block/buzz/pull/3741))
([`4933672eb4`](4933672eb4))
- feat(replica): portable heartbeat-token fence with snapshot-local
reader routing ([#3268](https://github.com/block/buzz/pull/3268))
([`63496cc1d4`](63496cc1d4))
- fix(git): channel binding tooling + author remediation for unbound
repos ([#3626](https://github.com/block/buzz/pull/3626))
([`788b3c002b`](788b3c002b))
- feat: configure S3 URL addressing style
([#3400](https://github.com/block/buzz/pull/3400))
([`7012d86d52`](7012d86d52))
- feat(tracing): correlate trace IDs in relay logs
([#3608](https://github.com/block/buzz/pull/3608))
([`005b5b819a`](005b5b819a))
- fix(relay): avoid subscription lock inversion
([#3413](https://github.com/block/buzz/pull/3413))
([`22be8bb351`](22be8bb351))
- feat(cli): add users set-status command for NIP-38 profile status
([#3253](https://github.com/block/buzz/pull/3253))
([`60158fce3e`](60158fce3e))
- feat(relay): make Postgres pool size configurable, default 50
([#3191](https://github.com/block/buzz/pull/3191))
([`2ce2d71cc3`](2ce2d71cc3))
- feat(tracing): add datastore tracing plumbing
([#2760](https://github.com/block/buzz/pull/2760))
([`e94b9aeda0`](e94b9aeda0))
- feat(invites): add use-limited invite links
([#3141](https://github.com/block/buzz/pull/3141))
([`d500c2d5cf`](d500c2d5cf))
- feat(admin): show reported message content in report detail
([#3149](https://github.com/block/buzz/pull/3149))
([`f069a85503`](f069a85503))
- resolve findings ([#3150](https://github.com/block/buzz/pull/3150))
([`9b0f744804`](9b0f744804))
- Revert "fix(cli,relay): resolve agents by verified owner"
([#3168](https://github.com/block/buzz/pull/3168))
([`a041e2d21e`](a041e2d21e))
- fix(cli,relay): resolve agents by verified owner
([#2615](https://github.com/block/buzz/pull/2615))
([`c3084b36d9`](c3084b36d9))
- fix(security): enforce durable community ban on NIP-43 relay-admin
kinds 9030-9033 ([#3128](https://github.com/block/buzz/pull/3128))
([`e2e0079101`](e2e0079101))
- fix(security): authorize kind:9000 role changes in both directions
([#3017](https://github.com/block/buzz/pull/3017))
([`00ecf2cac7`](00ecf2cac7))
- feat(desktop): handle project work from Inbox
([#3117](https://github.com/block/buzz/pull/3117))
([`c5c4f390b6`](c5c4f390b6))
- feat(relay): make per-owner community limit configurable via
BUZZ_MAX_COMMUNITIES_PER_OWNER
([#2599](https://github.com/block/buzz/pull/2599))
([`2a051a404d`](2a051a404d))
- feat(relay): add author-only-unless-shared read gate for kind 30175
([#2768](https://github.com/block/buzz/pull/2768))
([`ab3af82871`](ab3af82871))
- fix(core): block IPv6 transition SSRF targets
([#2801](https://github.com/block/buzz/pull/2801))
([`c26bf5945d`](c26bf5945d))
- fix(workflow): bypass system proxies for webhooks
([#2800](https://github.com/block/buzz/pull/2800))
([`60a171b19e`](60a171b19e))
- fix(audit): hash created_at at the precision Postgres stores
([#2638](https://github.com/block/buzz/pull/2638))
([`264a56a226`](264a56a226))
- feat(desktop): make pull request reviews actionable
([#2510](https://github.com/block/buzz/pull/2510))
([`9081ab0ec9`](9081ab0ec9))
- fix(relay): decompress gzip-encoded git smart-HTTP request bodies
([#2670](https://github.com/block/buzz/pull/2670))
([`5ca36e7b91`](5ca36e7b91))
- fix(sharing): preserve agent/team snapshot tEXt chunks through media
sanitization ([#2438](https://github.com/block/buzz/pull/2438))
([`b096b0a15a`](b096b0a15a))
- fix(relay): send 1012 restart close to all clients on graceful drain
([#2575](https://github.com/block/buzz/pull/2575))
([`1911c69aa2`](1911c69aa2))
- fix(media): sanitize animated image uploads
([#2524](https://github.com/block/buzz/pull/2524))
([`8f8f5fa5a4`](8f8f5fa5a4))
- fix(channels): strip leading hash prefixes from names
([#2250](https://github.com/block/buzz/pull/2250))
([`d0ab3fdb05`](d0ab3fdb05))
- feat(relay): make Redis pool size configurable, default 16
([#2521](https://github.com/block/buzz/pull/2521))
([`bcc3e13069`](bcc3e13069))
- feat(desktop+acp): spawn a harness per (agent, community) pair at GUI
startup — warm sockets, lazy LLM pool
([#2122](https://github.com/block/buzz/pull/2122))
([`61cc738ee8`](61cc738ee8))
- feat(media): add S3-truth per-community storage sweep
([#2044](https://github.com/block/buzz/pull/2044))
([`bd37a4d584`](bd37a4d584))
- feat(relay): log NIP-98 pubkey attribution on HTTP bridge requests
([#2206](https://github.com/block/buzz/pull/2206))
([`7e34bee62c`](7e34bee62c))
- Revert "feat(relay): inventory unreachable Git objects"
([#2275](https://github.com/block/buzz/pull/2275))
([`0fb820f9bf`](0fb820f9bf))
- feat(relay): inventory unreachable Git objects
([#2264](https://github.com/block/buzz/pull/2264))
([`3afc9dae15`](3afc9dae15))
- relay: add author_type label to buzz_events_stored_total
([#2243](https://github.com/block/buzz/pull/2243))
([`b9f54c43fe`](b9f54c43fe))
- fix(git): make project branch workflows reliable
([#2213](https://github.com/block/buzz/pull/2213))
([`166f27be4b`](166f27be4b))
- feat(cli): manage repository protection rules
([#2193](https://github.com/block/buzz/pull/2193))
([`f94324598d`](f94324598d))
- feat(cli): add agents archive/unarchive/archived subcommands
([#2173](https://github.com/block/buzz/pull/2173))
([`7d7992067b`](7d7992067b))
- fix(mobile): sanitize Android image uploads
([#2188](https://github.com/block/buzz/pull/2188))
([`ee21da90bd`](ee21da90bd))
- fix(cli): paginate channel directory queries
([#2181](https://github.com/block/buzz/pull/2181))
([`03fe19d603`](03fe19d603))
- fix(mobile): image upload fails due to unstripped metadata
([#2185](https://github.com/block/buzz/pull/2185))
([`37f15b2001`](37f15b2001))
- perf(relay): compact Git packs before manifest limits
([#2172](https://github.com/block/buzz/pull/2172))
([`80e0ab16b0`](80e0ab16b0))
- perf(relay): cache Git pack hydration
([#2169](https://github.com/block/buzz/pull/2169))
([`a4d82ec722`](a4d82ec722))
- fix(relay): bound and observe Git read operations
([#2167](https://github.com/block/buzz/pull/2167))
([`5f7c93d9c1`](5f7c93d9c1))
- relay: gate push enqueue on live leases; batch matcher pipeline
(T1b/T1a-repair/T2b) ([#2145](https://github.com/block/buzz/pull/2145))
([`e43b2d5aac`](e43b2d5aac))
- relay: add audit logging disable switch
([#2134](https://github.com/block/buzz/pull/2134))
([`bf5acabdde`](bf5acabdde))
- relay: skip TTL deadline bump for known-permanent channels (T1a
write-amp) ([#2125](https://github.com/block/buzz/pull/2125))
([`2e936d439c`](2e936d439c))
- fix(git): carry NIP-OA delegation in auth event
([#2120](https://github.com/block/buzz/pull/2120))
([`c12257d57a`](c12257d57a))
- Route lag-tolerant reads to an optional Postgres read replica
([#2084](https://github.com/block/buzz/pull/2084))
([`29c48883d3`](29c48883d3))
- fix: recover community access visibility
([#2074](https://github.com/block/buzz/pull/2074))
([`ca384d082d`](ca384d082d))
- feat: proxy feedback-scoped admin attachments
([#2059](https://github.com/block/buzz/pull/2059))
([`d7f918e3cb`](d7f918e3cb))
- feat: add read-only deployment moderation dashboard
([#1999](https://github.com/block/buzz/pull/1999))
([`68e670e001`](68e670e001))
- Bug-bash round 2: table scroll, Goose instructions, workflow mention
wake ([#2034](https://github.com/block/buzz/pull/2034))
([`64b8fea6dc`](64b8fea6dc))
- Strip media metadata on clients and reject it at the relay
([#2006](https://github.com/block/buzz/pull/2006))
([`5cfd69cb0c`](5cfd69cb0c))
- [codex] Hold Git concurrency permits through streaming (BUZZ-SEC-018)
([#1916](https://github.com/block/buzz/pull/1916))
([`7baea42abb`](7baea42abb))
- [codex] Enforce shared relay admission limits (BUZZ-SEC-019)
([#1917](https://github.com/block/buzz/pull/1917))
([`73fc0ec6cf`](73fc0ec6cf))
- [codex] Block banned actors from moderation commands (BUZZ-SEC-007)
([#1915](https://github.com/block/buzz/pull/1915))
([`caa195ca58`](caa195ca58))
- [codex] Fix relay WebSocket admission limits
([#1682](https://github.com/block/buzz/pull/1682))
([`d3ce971fc7`](d3ce971fc7))
- feat: add invite QR and mobile direct join
([#1957](https://github.com/block/buzz/pull/1957))
([`648cbf3610`](648cbf3610))
- fix(join-policy): require legal consent on hosted invites
([#1987](https://github.com/block/buzz/pull/1987))
([`2e1577f76f`](2e1577f76f))
- [codex] Prevent actor-tag UI impersonation
([#1931](https://github.com/block/buzz/pull/1931))
([`c540ec9678`](c540ec9678))
- Scope relay runtime state by community
([#1658](https://github.com/block/buzz/pull/1658))
([`d52dedb06f`](d52dedb06f))
- Apply optional relay join policy across join flows
([#1894](https://github.com/block/buzz/pull/1894))
([`6c2d667575`](6c2d667575))
- feat(media): require auth for relay media reads
([#1926](https://github.com/block/buzz/pull/1926))
([`f308762852`](f308762852))
- feat(relay): add community unarchive endpoint
([#1908](https://github.com/block/buzz/pull/1908))
([`6b9641db2b`](6b9641db2b))
- feat(relay): gate Git web GUI separately
([#1901](https://github.com/block/buzz/pull/1901))
([`34dc7dec75`](34dc7dec75))
- mesh: upgrade runtime, enforce membership, add shared compute provider
([#1656](https://github.com/block/buzz/pull/1656))
([`54638ff4bb`](54638ff4bb))
- Route Git scratch through configured volume
([#1884](https://github.com/block/buzz/pull/1884))
([`2318b3096c`](2318b3096c))
- feat(relay): gate usage metrics behind stable leader
([#1814](https://github.com/block/buzz/pull/1814))
([`59e9821503`](59e9821503))
- Relay mesh: cross-pod tunnel + huddle transport (buzz-relay-mesh)
([#1670](https://github.com/block/buzz/pull/1670))
([`ccb021d713`](ccb021d713))
- feat(push): deliver accepted relay events as wakes
([#1866](https://github.com/block/buzz/pull/1866))
([`bffbc5f22c`](bffbc5f22c))
- fix(db): resolve duplicate migration version
([#1863](https://github.com/block/buzz/pull/1863))
([`08ad38a07f`](08ad38a07f))
- Add private product feedback sidecar
([#1857](https://github.com/block/buzz/pull/1857))
([`af190c93e1`](af190c93e1))
- feat(relay): add durable community archival
([#1834](https://github.com/block/buzz/pull/1834))
([`2b15a72675`](2b15a72675))
- feat(push): add public APNs gateway
([#1770](https://github.com/block/buzz/pull/1770))
([`1c006822e4`](1c006822e4))
- feat(relay): add atomic community ownership transfer
([#1845](https://github.com/block/buzz/pull/1845))
([`52e42ccb9f`](52e42ccb9f))
- Bound NIP-RS retention and search indexing
([#1771](https://github.com/block/buzz/pull/1771))
([`1b4703021d`](1b4703021d))
- Add optional standalone pairing relay to Helm chart
([#1799](https://github.com/block/buzz/pull/1799))
([`9b47c8548f`](9b47c8548f))
- fix(relay): publish membership snapshot on provisioning
([#1761](https://github.com/block/buzz/pull/1761))
([`0950d392b7`](0950d392b7))
- feat(relay): per-community usage metrics
([#1723](https://github.com/block/buzz/pull/1723))
([`620822899a`](620822899a))
- refactor(desktop): remove vestigial MCP toolsets config
([#1776](https://github.com/block/buzz/pull/1776))
([`dfec75b3c0`](dfec75b3c0))

**To release:** merge this PR. The tag and build will happen
automatically.

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-08-08 12:26:24 -04:00
Michael Neale
38bf642fcf ci: prove the relay-driven mesh lifecycle — discover, join, infer, deny — with real nodes (#3862)
## Summary

CI now proves the full Buzz shared-compute join story end to end: a
member can discover another member's served model **through the Buzz
relay alone** and run inference over the mesh, while a non-member gets
nothing — the relay rejects its auth, and the mesh refuses to route for
it even holding a leaked endpoint address.

This is deliberately different from mesh-llm's own CI smokes (which
bootstrap two nodes with a hand-carried invite token / mdns): here the
**relay is the control plane**, exactly like the desktop app:

1. **Membership** — identities A and B are added via `buzz-admin`
(kind:13534 NIP-43 roster); C is not.
2. **Advertise** — each member publishes a client-signed kind:30003
discovery note carrying its MeshLLM owner binding and (for the serve
node) `serveTargets[].endpointAddr`, covered by an endpoint-binding
signature — the exact payload shape the desktop coordinator publishes.
3. **Trust** — the serve node derives its admission allowlist from the
relay (statuses ∩ roster) and requires the **exact expected {A, B}
owner-id set** before starting with `TrustPolicy::Allowlist`.
4. **Join** — the client verifies owner + endpoint bindings and
membership, then dials the relay-discovered endpoint (the desktop
join-watcher's `dial_endpoint_addr` step). No out-of-band token.
5. **Infer** — a chat completion against the client's local OpenAI
endpoint routes over QUIC to the serve node's model (CPU, SmolLM2-135M,
~105MB).
6. **Deny (differential)** — the stranger's NIP-42 auth must fail with
the relay's own membership rejection (`restricted: not a relay member` —
successful auth or any unrelated connect error fails the run), and
dialing the leaked endpoint must not produce a routed inference —
**while the trusted client re-proves inference immediately afterwards**,
so a dead serve node can't masquerade as an admission denial.

## What's in the PR

- `crates/buzz-relay/examples/mesh_relay_lifecycle_smoke.rs` — the
harness. One process per node (mesh-llm keeps process-global state under
`~/.mesh-llm`), orchestrator + serve/client/stranger roles,
byte-identical binding payloads to
`desktop/src-tauri/src/mesh_llm/identity.rs` (called out with
keep-in-sync comments). Child stdout is pumped through a reader thread
so every wait has a hard deadline; timed-out children are killed; exit
statuses are checked.
- `scripts/ci-mesh-lifecycle-smoke.sh` — provisions a membership-gated
relay (throwaway owner + signing identities via `buzz-admin
generate-key`), runs the harness, cleans up. Fails fast if :3000 is
already occupied (a stale open relay would mask gating).
- `scripts/start-relay-for-tests.sh` — gains opt-in NIP-43 membership
env passthrough (`BUZZ_REQUIRE_RELAY_MEMBERSHIP` + `RELAY_OWNER_PUBKEY`
+ `BUZZ_RELAY_PRIVATE_KEY`). Default behavior unchanged.
- `.github/workflows/mesh-lifecycle.yml` — separate, path-filtered,
non-required workflow (mesh paths, the harness's dependency crates,
`Cargo.lock`, dispatch), pinned to `ubuntu-24.04`. Caches the mesh
native runtime + HF model keyed on the lockfile hash, so a mesh pin bump
rolls the runtime cache. Uploads relay + harness logs on failure.

## Scope

This is an **independent protocol harness**: it speaks the same wire
protocol and payload shapes as the desktop but re-implements the
binding/verification logic (the desktop crate is outside the workspace).
Regressions inside the desktop's own discovery filtering are the desktop
unit tests' job; what this smoke proves is that the relay + mesh-llm SDK
+ admission stack support the lifecycle end to end.

## Relationship to mesh-llm's CI

Follows the shape mesh-llm's own CI proved stable (tiny CPU model, one
runner, multiple real mesh-llm processes over real QUIC — cf. their
`ci-two-node-client-serving-smoke.sh`), but swaps the token bootstrap
for the relay-driven lifecycle, which is the part only Buzz can test.

## Validation

Green on GitHub Actions (ubuntu-24.04) across three runs, including
after rebases onto the mesh v0.74 upgrade (#3467) and latest main:

```
PASS 1/6: relay-derived allowlist is exactly {A, B}
PASS 2/6: serve member ready + advertised model: jc-builds/SmolLM2-135M-Instruct-Q4_K_M-GGUF:Q4_K_M
PASS 3/6: client member discovered + joined via relay
PASS 4/6: inference routed over the mesh: "PONG"
PASS 5/6: relay rejected the stranger's NIP-42 auth (membership gate)
PASS 6/6: stranger denied (gossip visible, inference rejected: 503 all tunnels failed) while trusted inference still routes
PASS: full relay-driven mesh lifecycle verified
```

Also validated locally on macOS. `cargo fmt --all --check` and `cargo
clippy -p buzz-relay --all-targets -- -D warnings` pass.

## Notes

- The harness follows the repo's mesh `[dev-dependencies]` pin
automatically, so it doubles as a canary for future mesh upgrades (it
already caught the v0.73.1 → v0.74.0 bump during development).
- The stranger "deny" accepts either shape mesh-llm exhibits: no model
visibility at all, or gossip visibility with inference refused —
mesh-llm applies the receiving node's owner policy after the gossip
handshake, so admission gates *routing*, not gossip. The differential
trusted-inference re-check (PASS 6/6) is what makes that a real denial
rather than a dead server.
- Model-visibility windows are tunable via `MESH_CLIENT_WINDOW_SECS` /
`MESH_STRANGER_WINDOW_SECS` if shared runners prove slow — pin a longer
window in the workflow env rather than re-running the job.

---------

Signed-off-by: Michael Neale <michael.neale@gmail.com>
2026-08-05 23:13:16 -04:00
Tyler
4933672eb4 feat(mesh): upgrade embedded mesh to v0.74 and harden shared compute (split 1/2 of #3467) (#3741)
## Summary

This is **part 1 of 2** split out from #3467 (per Tyler's request),
carrying only the mesh-scoped changes. The agent/ACP response-behavior
changes and the new `send_message` tool stay in #3467 as part 2. All
commits are @michaelneale's work, cherry-picked with authorship
preserved.

- Upgrade embedded Mesh to v0.74.0 (tag-pinned instead of commit rev)
and use canonical Gemma model IDs.
- Keep shared compute serving through member joins, roster changes, app
recovery, and community switching.
- Wait for actual model readiness and avoid resuming incomplete
downloads after quit.
- Leave `BUZZ_AGENT_THINKING_EFFORT` unset by default so each model's
chat template picks its own thinking default (`none` suppressed Gemma
tool-calling entirely; pinning `low` made Qwen3 burn ~4x output budget).
Explicit agent/persona/global values still win.

## Relationship to #3467

Contains the mesh commits from #3467 (`2cd640b23`, `0ad81c341`,
`ad13ed841`) rebased onto current main, with one deliberate exclusion:
the `crates/buzz-agent/src/llm.rs` reasoning→text parser change from
`2cd640b23` is **not** here. That change unconditionally affects every
OpenAI-compat/Responses provider, so it belongs with the reply-behavior
work in part 2, where it can be reviewed as what it is.

Not included (remaining in #3467 / part 2):
- typed `send_message` tool in dev-mcp + `BUZZ_ACP_SEND_MESSAGE_TOOL`
gating
- plain-reply delivery fallback in buzz-acp
(`BUZZ_ACP_DELIVER_PLAIN_REPLIES`)
- the mesh_agent_e2e P5/P6 rewrite (exists to prove the reply path)
- the two `env.insert` preset opt-ins in `relay_mesh.rs` for the flags
above
- the llm.rs parser change

This PR is independently mergeable; part 2's flags are all off by
default so it can land before or after.

## Testing

- `cargo test -p buzz-relay --locked` — 780 passed (one telemetry test
is order-sensitive under parallel default settings; passes in the
pre-push suite and standalone, unrelated to this diff — files untouched
here).
- `just desktop-tauri-test` (default features) — 1877 passed.
- `cargo test --locked --features mesh-llm` in `desktop/src-tauri` —
1961 passed, including the new relay-mesh preset and
coordinator/recovery tests.
- Both `Cargo.lock`s resolve with `--locked` against the v0.74.0 tag.
- Full pre-push hook suite green (rust-tests, desktop-check/test, tauri
checks).

Live validation of the mesh v0.74 upgrade itself is documented on #3467
(two-Mac cross-version test).

---------

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-07-30 11:37:27 -04:00
Dave Grochowski
e94b9aeda0 feat(tracing): add datastore tracing plumbing (#2760)
Configure a dedicated datastore tracing target on the OTLP layer while
preserving explicit logging filters and avoiding span overhead when OTLP
is disabled.

This is in preparation for adding trace spans for datastores used in
Buzz

## Update — 2026-07-27

- Export HTTP requests as `INFO` server spans under `buzz_relay`,
preserving request parentage for datastore spans.
- Configure OTEL span filtering independently with `BUZZ_OTEL_FILTER`,
so `RUST_LOG` changes cannot break trace topology.
- Verify exported HTTP and datastore spans share a trace ID and have the
expected parent/child relationship.

Co-authored-by: Amp <amp@ampcode.com>
2026-07-27 23:32:42 -04:00
Kaal
5ca36e7b91 fix(relay): decompress gzip-encoded git smart-HTTP request bodies (#2670)
Signed-off-by: Kaal <kaal@shib.io>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-07-23 22:37:55 -07:00
Will Pfleger
bd37a4d584 feat(media): add S3-truth per-community storage sweep (#2044)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-22 12:32:52 -04:00
Jordan Mecom
d3ce971fc7 [codex] Fix relay WebSocket admission limits (#1682) 2026-07-17 16:23:45 +00:00
Tyler
6c2d667575 Apply optional relay join policy across join flows (#1894)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler Longwell <tlongwell@squareup.com>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: klopez4212 <klopez4212@gmail.com>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
2026-07-16 13:59:53 -04:00
Michael Neale
54638ff4bb mesh: upgrade runtime, enforce membership, add shared compute provider (#1656) 2026-07-15 10:10:29 -04:00
Will Pfleger
59e9821503 feat(relay): gate usage metrics behind stable leader (#1814)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-14 19:19:31 -04:00
Tyler
ccb021d713 Relay mesh: cross-pod tunnel + huddle transport (buzz-relay-mesh) (#1670)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler Longwell <tlongwell@squareup.com>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6 <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-14 16:56:48 -04:00
Tyler
bffbc5f22c feat(push): deliver accepted relay events as wakes (#1866)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-14 16:13:04 -04:00
Will Pfleger
0d9be2fde1 chore(release): release Buzz Relay version 0.2.0 (#1728) 2026-07-10 16:43:23 -04:00
Will Pfleger
b1d9d955de feat(relay): add OpenTelemetry tracing, keep Prometheus metrics (#1398)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-01 16:05:59 -04:00
Tyler
3292b502aa fix(relay): enable Redis TLS for rediss:// (ElastiCache) (#1417)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-06-30 21:14:43 -04:00
Tyler
14fba21e57 Multi-tenant Buzz relay: community_id as a server-resolved key (comprehensive rewrite) (#1321)
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Sami <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Quinn <96f056ad5f2305c8ddf637dc65d048aa4c12d7daeb8867690e34fca46b0ef64c@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Sami <sami@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
2026-06-29 12:39:02 -04:00
Will Pfleger
68a0cc8506 chore(release): release Buzz Relay version 0.1.1 (#1269) 2026-06-24 23:49:09 -04:00
Tyler
856815994c perf(relay/git): stream read-path, manifest info/refs fast path, idx sidecar (A/B/C) (#1240)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
2026-06-24 19:44:24 -04:00
Will Pfleger
549b7d2481 fix(release): publish versioned relay Docker tags via independent release lanes (#1173)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-06-23 18:35:30 -04:00
Will Pfleger
d99ad131f1 refactor: rename sprout backend to buzz (#958)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <wpfleger@block.xyz>
Signed-off-by: Will Pfleger <wpfleger@squareup.com>
Signed-off-by: Will Pfleger <wpfleger96@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw <4a1bfa0013bc6d14a8d600d8bf6392efefbd2a26ac3c96c9b2a106b0d12297ca@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub16v54tttfqacx9ycvc3k0ut0npj564ahcuajzy6qjvh57ntmsf4uq4806j2 <d32955ad69077062930cc46cfe2df30ca9aaf6f8e76422681265e9e9af704d78@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Will Pfleger <wpfleger96@gmail.com>
2026-06-10 19:29:51 -04:00