Commit Graph
418 Commits
Author SHA1 Message Date
ab3af82871 feat(relay): add author-only-unless-shared read gate for kind 30175 (#2768)
Kind 30175 persona sync events carry plaintext `system_prompt` and
`respond_to_allowlist`. This PR adds **author-only-unless-shared read
semantics**: events without `["shared","true"]` are visible only to the
author; events with that tag are community-readable.

## What changed

### New read class (kind 30175)
Kind 30175 gets per-event gating at every relay read surface. The
`shared` marker is a **tag**, not a content field, so content bytes
(which double as the `source_version` drift basis) are not affected when
toggling share state.

### `event_visible_to_reader` helper (`handlers/req.rs`)
Centralizes the three per-event access predicates —
`is_author_only_event`, `is_unshared_persona_event`,
`reader_authorized_for_event` — into one `pub(crate)` fn callable from
both WS and HTTP adapters. All result-visibility sites now call this
single helper.

### NIP-98 HTTP bridge (`api/bridge.rs`)
- `POST /query` catchall: replaced the two-step author-only +
result-gated checks with `event_visible_to_reader` (now also covers the
persona shared-gate).
- `POST /count`: added `needs_persona_filtering` to the fast-path guard
(forces per-event fallback when filter can match `kind:30175`) and
replaced both fallback loops' individual checks with
`event_visible_to_reader`.
- FTS `/search` bridge helper: replaced `is_author_only_event` with
`event_visible_to_reader` as defense-in-depth (30175 is not in the FTS
allowlist today; comment at site explains the future-proofing intent).

### Ingest validation (`handlers/ingest.rs`)
`validate_persona_envelope` rejects malformed `shared` tags: wrong
value, missing value, duplicates. Accepts exactly `["shared","true"]`
and tag-absent.

### Kind helpers (`buzz-core/src/kind.rs`)
`is_persona_shared_kind`, `is_unshared_persona_event`,
`filter_can_match_persona_shared_kinds`.

### Tests (`e2e_persona.rs`)
8 unit tests in `kind.rs`, 6 in `ingest.rs`, 8 e2e tests total:
- AC-1–6 covering the gated surfaces
- `test_persona_live_fanout_shared_gate`: reworked with explicit
monotonic `created_at` timestamps (t0 < t1 < t2) and per-step head
assertions, eliminating the NIP-33 event-id tie-break race. Also asserts
foreign live subscription receives nothing on shared→unshared
transition.
- `test_persona_ingest_shared_tag_validation`: added `shared=x` and
missing-value wire-level rejection cases.
- `test_persona_mixed_kind_filter_does_not_leak`: publishes a kind-9
event and asserts it IS returned; absence-only assertion no longer
sufficient.
- `test_persona_http_query_cross_author_gate`: NIP-98 `/query`
cross-author gate (authors filter, kindless `ids` — both blocked; shared
`ids` — passes).
- `test_persona_http_count_cross_author_gate`: NIP-98 `/count`
cross-author gate (foreign sees 1/shared, author sees all, wildcard
checked).

### NIP-AP.md
Replaced aspirational "every relay read chokepoint" wording with an
enumerated list of gated surfaces including NIP-98 `/query`, `/count`,
and FTS/search with their enforcement mechanism named. Added
**Non-goal** note for side-band existence oracles
(reaction/report/deletion target resolution).

## Existing tests
All pre-existing `e2e_persona` tests use `{ids:[event_id]}` or
`{authors:[self]}` filters — author self-reads bypass the gate and are
unaffected.

## Gates
`just check` ✅ | `just test-unit` ✅ | `cargo test -p buzz-relay` ✅ (749
passed, 1 pre-existing failure in
`demo_join_forwarded_arm_round_trips_echo` — flaky on `main`, unrelated
to this PR, verified red at `origin/main` before this branch)

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-24 23:17:30 -04:00
c26bf5945d fix(core): block IPv6 transition SSRF targets (#2801)
## Summary

- classify IPv4-compatible, IPv4-mapped, and SIIT IPv4-translated IPv6
addresses using the existing IPv4 SSRF policy
- decode IPv4 destinations under the RFC 6052 well-known NAT64 prefix
- conservatively block local-use NAT64, Teredo, and 6to4 ranges
- add boundary coverage for every newly handled transition prefix

## Why

The workflow webhook SSRF guard previously recognized IPv4-mapped IPv6
addresses but not other standardized IPv6 forms that can embed or route
to IPv4 destinations. Private, loopback, or link-local IPv4 targets
represented through those forms could therefore pass address
classification.

This also covers the legacy SIIT IPv4-translated prefix
(`::ffff:0:0:0/96`), which Rust's `Ipv6Addr::to_ipv4()` does not
recognize but an SIIT-enabled network may route to the IPv4 value in the
final 32 bits.

Network-specific NAT64 prefixes remain a deployment concern and should
be restricted through egress policy; they cannot be inferred generically
from an IPv6 address.

## Test plan

- `cargo fmt --all -- --check`
- `cargo test -p buzz-core network` (35 passed)
- `cargo clippy -p buzz-core --all-targets -- -D warnings`
- `git diff --check`

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-07-24 22:47:58 -04:00
60a171b19e fix(workflow): bypass system proxies for webhooks (#2800)
## Summary

Disable automatic system-proxy discovery for workflow webhook requests.

## Why

Webhook destinations are resolved, validated, and pinned before the
request to prevent DNS-rebinding SSRF. If reqwest uses a system proxy,
the proxy can resolve the original hostname itself instead of connecting
to the validated address, bypassing that pinning guarantee.

Calling `no_proxy()` keeps these security-sensitive requests on the
directly validated connection path. Redirects remain disabled.

## Test plan

- `cargo fmt --all -- --check`
- `cargo test -p buzz-workflow --features reqwest` (149 passed)
- `cargo clippy -p buzz-workflow --all-targets --features reqwest -- -D
warnings`
- `git diff --check`

Co-authored-by: Amp <amp@ampcode.com>
2026-07-24 22:24:47 -04:00
Shani SinghandGitHub 264a56a226 fix(audit): hash created_at at the precision Postgres stores (#2638)
Fixes #2637 — full analysis and reproduction there.

## Problem

Audit entries are stamped and hashed with `Utc::now()` (nanoseconds),
then stored in a `TIMESTAMPTZ` column (microseconds). `compute_hash`
covers `created_at.to_rfc3339()`, and chrono emits 0/3/6/**9**
fractional digits depending on the value — so the digest written at
`service.rs:103` is computed over `…T12:00:00.123456789+00:00` while
`verify_chain` recomputes over the `…T12:00:00.123456+00:00` that
Postgres hands back.

Every hash chain backed by a real database therefore fails verification
at its first entry, on untampered data. That is not just a broken
feature — it means a genuinely forged row is indistinguishable from the
permanent baseline failure, so `HashMismatch` carries no signal.

It is invisible in CI because all six chain tests are `#[ignore =
"requires Postgres"]`, and the in-process `hash.rs` tests use a fixture
timestamp of `2026-01-01T00:00:00Z` — zero sub-seconds, the one value
where the bug cannot appear.

## Solution

Reduce `created_at` to the stored precision *before* hashing, so the
in-memory entry and the row are byte-identical:

```rust
pub fn to_storage_precision(created_at: DateTime<Utc>) -> DateTime<Utc> {
    created_at.trunc_subsecs(6)
}
```

`log_inner` is the only place that assigns `created_at` — every caller
goes through `NewAuditEntry`, which carries no timestamp — so this is a
single choke point. It is wrapped in a `log_timestamp()` helper purely
so the invariant is assertable without a database.

I chose truncation at the write path over the alternative (hashing a
precision-independent encoding such as
`timestamp_micros().to_be_bytes()`). Both fix the mismatch, but
truncating keeps the existing hash preimage format and gives the
stronger invariant: the `AuditEntry` returned from `log()` is now
exactly what a later read returns.

Truncation matches what actually happens on the wire — sqlx encodes
`DateTime<Utc>` as microseconds since the Postgres epoch, truncating —
so the value hashed is the value stored.

## Validation

Toolchain note: built on Windows with the `x86_64-pc-windows-gnu`
toolchain (no MSVC linker locally).

**Before**, against Postgres 17 with `migrations/*` applied:

```
$ cargo test -p buzz-audit --lib -- --ignored --test-threads=1

test service::tests::chain_links_within_one_community ... FAILED
test service::tests::chains_are_independent_per_community ... FAILED
test service::tests::community_chain_starts_at_seq_1_with_null_prev ... ok
test service::tests::cross_community_row_does_not_verify ... ok
test service::tests::verify_detects_tampering_within_a_community ... FAILED
test service::tests::verify_empty_range_is_false ... ok

test result: FAILED. 3 passed; 3 failed
```

with `HashMismatch { seq: 2 }` / `HashMismatch { seq: 1 }` on untampered
chains.

**After**, same database:

```
test result: ok. 6 passed; 0 failed
```

`verify_detects_tampering_within_a_community` is the one to look at: it
asserts `HashMismatch` lands on the *tampered* entry's `seq`. It was
failing because verification already blew up on an earlier untampered
row — so the assertion proving tamper detection works had never actually
been exercised. It passes now.

Also:
- `cargo test -p buzz-audit --lib` (no Postgres) — 12 passed, 0 failed.
- `cargo clippy -p buzz-audit --all-targets -- -D warnings` — clean.
- `cargo fmt -p buzz-audit -- --check` — clean.

## New tests

Three in `hash.rs`, none needing Postgres:

- `storage_precision_drops_sub_microsecond_digits` — the helper's
contract, and that it is idempotent so a re-read value is unchanged.
- `nanosecond_timestamps_cannot_survive_a_database_round_trip` — asserts
the digests **differ**. This is the trap itself, written down so the
next person changing the hash preimage sees why the precision reduction
is load-bearing.
- `storage_precision_timestamps_survive_a_database_round_trip` — the
invariant the write path must hold.

Plus `log_timestamp_carries_no_sub_microsecond_digits` in `service.rs`,
deliberately **not** `#[ignore]`d, so a regression on the write path is
caught by `just test-unit` instead of only by Postgres-gated tests that
normally never run.

## Compatibility

Rows written before this stay unverifiable — they always were — so there
is no migration. An operator relying on an existing chain has to
re-anchor.

## Relationship to #2620

#2620 proposes a shared `verify_entries` walk (anchoring, seq
contiguity, tail-truncation detection) plus a `buzz-admin audit verify`
command. Its Postgres-free unit tests build entries in memory and would
pass regardless, but its `#[ignore]` Postgres tests and the operator
command itself would fail on every real chain until this lands. Worth
taking this first so that work has a verifiable baseline — the two
changes don't overlap in code.

---------

Signed-off-by: Shani Singh <teamdeveloperworld@gmail.com>
2026-07-24 19:28:39 -04:00
0a9c26ee8c fix(acp): dead-letter auth errors immediately with re-auth hint (#2751)
## Problem

Auth-class errors (expired OAuth token, HTTP 401) are non-retryable: the
token won't self-repair between attempts. Today, `PromptOutcome::Error`
for an application-class error falls into the generic `queue.requeue()`
path, burning up to 10 retry slots over a long backoff window before
dead-lettering. Will's canary run observed the 401 message being retried
repeatedly.

## Solution

Add `is_auth_error()` that classifies `AcpError::AgentError` messages
matching two narrow patterns observed in the field:

- `"Re-authenticate"` — emitted by the Claude CLI for expired OAuth
tokens
- `"API Error: 401"` — present in Claude/Codex HTTP-401 responses

Conservative matching is intentional: a false positive (misclassifying a
transient error as non-retryable) silently drops a user message, which
is worse than a false negative (extra retries on an auth error).

In `handle_prompt_result`, a new branch intercepts the failing batch
before `queue.requeue()` for auth-class errors and dead-letters
immediately, posting a user-visible notice to re-authenticate the CLI
(e.g. `claude /login` or `codex login`).

The transport/application split in `PromptOutcome::Error` is untouched —
this only changes batch fate after an application-class auth error.

## Tests

6 new tests in `error_outcome_emission_tests`:
1. `is_auth_error` matches `Re-authenticate` message
2. `is_auth_error` matches `API Error: 401` message
3. `is_auth_error` rejects other `AgentError` messages (usage credits,
etc.)
4. `is_auth_error` rejects transport errors (I/O, WriteTimeout)
5. Auth error dead-letters immediately — 0 pending channels after
`handle_prompt_result`
6. Non-auth application error still requeued — 1 pending channel after
`handle_prompt_result`

Full `cargo test -p buzz-acp`: 598/598 passing.

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-24 17:20:24 -04:00
thomaspblockandGitHub 9081ab0ec9 feat(desktop): make pull request reviews actionable (#2510) 2026-07-24 11:34:25 -04:00
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
5afa16157a fix(desktop): suppress Windows console flashes and reject WSL bash alias (#2587)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-23 18:27:40 -04:00
b096b0a15a fix(sharing): preserve agent/team snapshot tEXt chunks through media sanitization (#2438)
Signed-off-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Co-authored-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
2026-07-23 13:40:15 -07:00
cb42c8d5b6 fix(acp): restrict DM turns to owner and verified siblings (#2591)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
2026-07-23 13:39:59 -07:00
1911c69aa2 fix(relay): send 1012 restart close to all clients on graceful drain (#2575)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-07-23 13:16:12 -07:00
df0a086177 fix(cli): install rustls crypto provider to unbreak WSS publishes in release builds (#2590)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-23 15:35:19 -04:00
8f8f5fa5a4 fix(media): sanitize animated image uploads (#2524)
Co-authored-by: Codex <noreply@openai.com>
2026-07-23 10:30:11 -07:00
d0ab3fdb05 fix(channels): strip leading hash prefixes from names (#2250)
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: npub1z3hmzc9ryehxzedl5wzlvpyvja0d483peaja5zt6pd0209f9x2jspe2dxh <146fb160a3266e6165bfa385f6048c975eda9e21cf65da097a0b5ea7952532a5@buzz.block.builderlab.xyz>
Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Co-authored-by: npub1z3hmzc9ryehxzedl5wzlvpyvja0d483peaja5zt6pd0209f9x2jspe2dxh <146fb160a3266e6165bfa385f6048c975eda9e21cf65da097a0b5ea7952532a5@buzz.block.builderlab.xyz>
Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
2026-07-23 12:56:10 -04:00
bcc3e13069 feat(relay): make Redis pool size configurable, default 16 (#2521)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-07-23 07:55:44 -07:00
+2 61cc738ee8 feat(desktop+acp): spawn a harness per (agent, community) pair at GUI startup — warm sockets, lazy LLM pool (#2122)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Matt Toohey <contact@matttoohey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: npub1hwqy0rnujtl25dzmlhn8qwux4kr8sjhas3ugltx9j5dm5dwkp2dsqjhytw <bb80478e7c92feaa345bfde6703b86ad86784afd84788facc5951bba35d60a9b@buzz.block.builderlab.xyz>
2026-07-22 13:24:46 -07:00
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
7e34bee62c feat(relay): log NIP-98 pubkey attribution on HTTP bridge requests (#2206)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-21 23:28:16 +00:00
TylerandGitHub 0fb820f9bf Revert "feat(relay): inventory unreachable Git objects" (#2275) 2026-07-21 13:09:07 -07:00
thomaspblockandGitHub 3afc9dae15 feat(relay): inventory unreachable Git objects (#2264) 2026-07-21 22:03:24 +02:00
b9f54c43fe relay: add author_type label to buzz_events_stored_total (#2243)
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
2026-07-21 11:50:42 -07:00
9a788c7aee fix(acp): pace relay observer frames (6/s + 90/min, zero burst) (#2217)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
2026-07-21 09:57:23 -07:00
7b25950fca fix(cli): retry transient relay failures and raise timeouts (#2196)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-21 12:17:44 -04:00
thomaspblockandGitHub 166f27be4b fix(git): make project branch workflows reliable (#2213) 2026-07-21 12:58:39 +02:00
4de3e04119 fix(acp): honor relay rate limits and pace resubscribes on bad links (#2199)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1067mpdna4vy22u9eltmmhtdfw56kww6ve2aze025dtfm4pxg07nqztjfhm <7ebdb0b67dab08a570b9faf7bbada97535673b4ccaba2cbd546ad3ba84c87fa6@sprout-oss.stage.blox.sqprod.co>
2026-07-21 03:21:23 -04:00
thomaspblockandGitHub f94324598d feat(cli): manage repository protection rules (#2193) 2026-07-21 08:57:08 +02:00
daf1f40a52 feat(cli): filter archived instances from --template roster resolution (#2207)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-21 02:02:44 -04:00
cd6b573f8d fix(buzz-acp,buzz-agent): surface stall duration and fate (#2204)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-21 01:10:28 -04:00
Will PflegerandGitHub 7d7992067b feat(cli): add agents archive/unarchive/archived subcommands (#2173) 2026-07-20 23:33:11 -04:00
Will PflegerandGitHub 0791fff8d2 chore(acp): strip stale finding-number references from comments (#2202) 2026-07-20 23:28:47 -04:00
ee21da90bd fix(mobile): sanitize Android image uploads (#2188)
Signed-off-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
2026-07-20 22:18:30 -04:00
03fe19d603 fix(cli): paginate channel directory queries (#2181)
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
2026-07-20 19:22:11 -04:00
Will PflegerandGitHub 0f86a608b9 fix(timeout): unified turn-timeout fix — cap inheritance, steer renewal, activity-aware requeue, LLM stall surfacing (#2175) 2026-07-20 18:20:57 -04:00
37f15b2001 fix(mobile): image upload fails due to unstripped metadata (#2185)
Signed-off-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co>
2026-07-20 21:39:19 +00:00
thomaspblockandGitHub 80e0ab16b0 perf(relay): compact Git packs before manifest limits (#2172) 2026-07-20 19:36:28 +02:00
1a94146181 feat(cli): add channels create --template for desktop channel templates (#1990)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-20 12:55:40 -04:00
thomaspblockandGitHub a4d82ec722 perf(relay): cache Git pack hydration (#2169) 2026-07-20 16:50:11 +02:00
thomaspblockandGitHub 5f7c93d9c1 fix(relay): bound and observe Git read operations (#2167) 2026-07-20 15:02:49 +02:00
e43b2d5aac relay: gate push enqueue on live leases; batch matcher pipeline (T1b/T1a-repair/T2b) (#2145)
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-07-19 21:42:58 -04:00
thomaspblockandGitHub 7f769b2439 fix(desktop): align inbox layout and draft details (#2143)
Approved
2026-07-20 00:53:53 +02:00
bf5acabdde relay: add audit logging disable switch (#2134)
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
2026-07-19 15:09:42 -04:00
klopez4212andGitHub 2b0f5e9f80 Improve agent runtime settings (#2026) 2026-07-19 19:01:38 +00:00
2e936d439c relay: skip TTL deadline bump for known-permanent channels (T1a write-amp) (#2125)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-19 14:55:51 -04:00
e25ed00248 docs(buzz-acp): fold hard-earned operating learnings into base prompt (#2129)
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-07-19 14:05:17 -04:00
75069650a3 fix(acp): teach agents to send real newlines (#2121)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-19 09:56:16 -07:00
c12257d57a fix(git): carry NIP-OA delegation in auth event (#2120)
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
2026-07-19 11:29:26 -04:00
29c48883d3 Route lag-tolerant reads to an optional Postgres read replica (#2084)
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-07-18 22:45:33 -04:00
5c359deb9b fix(cli): report presence subject (#2104)
Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
2026-07-18 20:41:05 -04:00
284a76c1c7 fix(agents): stop the reply loop and the premature kickoff closer (#2094)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-18 16:29:17 -07:00
ca384d082d fix: recover community access visibility (#2074)
Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@sprout-oss.stage.blox.sqprod.co>
2026-07-18 19:01:03 +00:00