Skip to content

fix(desktop): fetch join policies through native networking - #2862

Merged
johnmatthewtennant merged 4 commits into
block:mainfrom
johnmatthewtennant:jtennant/fix-add-community-policy-fetch
Jul 27, 2026
Merged

fix(desktop): fetch join policies through native networking#2862
johnmatthewtennant merged 4 commits into
block:mainfrom
johnmatthewtennant:jtennant/fix-add-community-policy-fetch

Conversation

@johnmatthewtennant

@johnmatthewtennant johnmatthewtennant commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Context

Adding an existing community by relay URL could fail with Community rejected: Load failed even when its WebSocket endpoint was reachable. The Add Community flow fetched /api/join-policy from the WebView, so a relay without a matching CORS allowance blocked the policy request before the app could join it.

Summary

This bug fix fetches join policies through Tauri's native networking layer for direct URL joins. Invite-code discovery, policy acceptance, and signed invite claims remain on the WebView path so those operations can migrate together later.

Changes

  • Uses native networking for Add Community and first-community direct URL join-policy requests.
  • Validates relay schemes, rejects URLs containing credentials, and refuses redirects.
  • Bounds declared and chunked native responses before JSON parsing.
  • Preserves existing 404, non-success status, malformed JSON, and absent-policy behavior.
  • Requires every join-policy caller to choose its transport explicitly.

Public relays using Buzz's default permissive CORS configuration are not known to be affected.

Related issue

Related to #2872.

Testing

Reviewer-reproducible examples

End-to-end red/green requires a relay with restrictive CORS and a Buzz identity authorized to join it.

Red: main

From a clean checkout of main:

. ./bin/activate-hermit
just staging

In Buzz Desktop:

  1. Add another community so the restrictive-CORS relay can be removed.
  2. Remove that relay.
  3. Open Add Community and enter the relay's WebSocket URL.
  4. Select Add Community.

Observed result:

Community rejected: Load failed
Green: this PR

From a clean checkout of this branch:

. ./bin/activate-hermit
just staging

Repeat the same steps above.

Observed result:

The community rejoins successfully.

Supporting checks:

  • Six native join-policy tests, including oversized declared and chunked responses.
  • Four TypeScript API tests, including the native command contract.
  • E2E build and four focused onboarding and sidebar Playwright tests.
  • Full just ci and pre-push suites.
  • Builderbot, Kalvin, and minimize-diff review fanout found no actionable issues after the final rebase.

@johnmatthewtennant
johnmatthewtennant marked this pull request as ready for review July 25, 2026 16:55
@johnmatthewtennant
johnmatthewtennant requested a review from a team as a code owner July 25, 2026 16:55
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/fix-add-community-policy-fetch branch from 45113e5 to 238526f Compare July 25, 2026 17:25

@bp2m6v4sp5-dev bp2m6v4sp5-dev left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submit

@wpfleger96 wpfleger96 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 hey @johnmatthewtennant — I like the direction here, native networking is clearly the right escape hatch for a CORS-restricted relay, and the redirect refusal + credential rejection are nice hardening on top. Two things I'd want changed before this goes in, plus a few smaller notes inline.

Blocking, both left as inline comments:

  1. the native command buffers the whole response body from an arbitrary user-entered relay (response.json())
  2. transport defaults to "webview" — the broken path is the default a new caller gets

Non-blocking notes:

desktop/src/shared/api/invites.test.mjs still only exercises the webview branch (every getJoinPolicy call in it omits the transport arg). Worth one native-transport case that pins the command name fetch_join_policy, the relayUrl arg shape, and the mapping — the two branches aren't symmetric (webview unwraps raw.policy, native returns the already-unwrapped policy), and right now nothing on the TS side locks that down.

The reported bug still reproduces for invite-URL joins against the same relay, since getJoinPolicy on the invite path, acceptJoinPolicy, and claimInvite all stay on webview fetch. I get why (the description says as much) — could you file a follow-up issue and link it here so the remaining half doesn't get lost?

Nothing here looks wrong to me on the parts I didn't comment on: 404/non-success/malformed-JSON semantics match the old flow, and I ran the URL builder against .. traversal, %2F-encoded segments, IPv6 hosts, uppercase schemes, and bare ws:///foo — all either rejected or normalized sanely.

Comment thread desktop/src-tauri/src/commands/join_policy.rs Outdated
Comment thread desktop/src/shared/api/invites.ts Outdated
Comment thread desktop/tests/e2e/sidebar.spec.ts
Comment thread desktop/src/features/communities/ui/CommunityEditForm.tsx
Comment thread desktop/src/features/onboarding/ui/InviteRedeemForm.tsx

@wpfleger96 wpfleger96 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Rechecked the review fixes at exact head 29b65c86e5a3013641be51277d812081a64c7422. The native response now has declared-length and streamed byte caps with both oversize cases tested; transport is required and explicit at every caller; the native TypeScript contract test is in place; stale route mocks are gone; the description is scoped to direct URL joins; and the remaining invite-path CORS work is linked as #2872. I don’t see any remaining blocker.

@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/fix-add-community-policy-fetch branch 3 times, most recently from 55ec210 to aeb63dd Compare July 27, 2026 20:54
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/fix-add-community-policy-fetch branch from aeb63dd to ac3f052 Compare July 27, 2026 21:08
@johnmatthewtennant
johnmatthewtennant merged commit 0019f80 into block:main Jul 27, 2026
25 checks passed
@johnmatthewtennant
johnmatthewtennant deleted the jtennant/fix-add-community-policy-fetch branch July 27, 2026 21:53
tlongwell-block pushed a commit that referenced this pull request Jul 28, 2026
* origin/main: (70 commits)
  feat(relay): make Postgres pool size configurable, default 50 (#3191)
  Publish symbol-bearing debug relay images (#3250)
  feat(tracing): add datastore tracing plumbing (#2760)
  fix(buzz-acp): accept id-keyed config options when resolving model switch (#2795)
  fix(desktop): probe legacy Goose install dir on Windows (#3248)
  refactor(desktop): extract install command execution into install_exec (#3251)
  Polish composer activity layout and transitions (#3151)
  feat(invites): add use-limited invite links (#3141)
  fix(node): bump Buzz-supplied Node runtimes past OpenClaw's >=24.15.0 floor (#3218)
  fix(desktop): preserve thread anchor through layout reflow (#3212)
  feat(search): parse from:/in:/after:/before: and pass them in the filter (#2871)
  fix(desktop): fetch join policies through native networking (#2862)
  fix(desktop): republish agent identity records when a persona rename propagates (#2607)
  fix(desktop): keep project Inbox previews compact (#3193)
  Inbox refactor (#2045)
  Fix composer selection formatting and drop overlay (#3172)
  Refine pending message status (#3153)
  feat(admin): show reported message content in report detail (#3149)
  fix(desktop): recover full local storage on startup (#3182)
  Replace mobile reconnect banners with skeleton shimmer (#3143)
  ...

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
wesbillman added a commit that referenced this pull request Jul 28, 2026
## Buzz Desktop release v0.5.0

### Changes since v0.4.26:

- feat(invites): add use-limited invite links
([#3141](#3141))
([`d500c2d5c`](d500c2d))
- fix(node): bump Buzz-supplied Node runtimes past OpenClaw's >=24.15.0
floor ([#3218](#3218))
([`98a7b1334`](98a7b13))
- fix(desktop): preserve thread anchor through layout reflow
([#3212](#3212))
([`9810d8545`](9810d85))
- feat(search): parse from:/in:/after:/before: and pass them in the
filter ([#2871](#2871))
([`cb2a265b5`](cb2a265))
- fix(desktop): fetch join policies through native networking
([#2862](#2862))
([`0019f8076`](0019f80))
- fix(desktop): republish agent identity records when a persona rename
propagates ([#2607](#2607))
([`7ca0bbd94`](7ca0bbd))
- fix(desktop): keep project Inbox previews compact
([#3193](#3193))
([`de1396050`](de13960))
- Inbox refactor ([#2045](#2045))
([`2bd4c24b7`](2bd4c24))
- Fix composer selection formatting and drop overlay
([#3172](#3172))
([`99da5b7eb`](99da5b7))
- Refine pending message status
([#3153](#3153))
([`75588eaff`](75588ea))
- fix(desktop): recover full local storage on startup
([#3182](#3182))
([`174c38e4b`](174c38e))
- fix(desktop): keep collapsed table separators out of spoilers
([#3169](#3169))
([`4d8b676bb`](4d8b676))
- feat(desktop): redesign agent runtime settings
([#3093](#3093))
([`d98da7389`](d98da73))
- fix(desktop): use forward slashes for git credential.helper on Windows
([#3023](#3023))
([`899531684`](8995316))
- chore(desktop): add AgentCreationPreview file-size override to unblock
main CI ([#3154](#3154))
([`b92a1f4bf`](b92a1f4))
- fix(desktop): make the test loader work on Windows
([#2758](#2758))
([`8bb43d519`](8bb43d5))
- fix(desktop): make lint and unit-test gates work on Windows
([#2943](#2943))
([`545bb46b8`](545bb46))
- feat(desktop): add search to agent emoji picker
([#2630](#2630))
([`313f793c8`](313f793))
- fix(desktop): keep identity key help dialog readable in dark mode
([#2854](#2854))
([`be275cfc6`](be275cf))
- feat(acp): title agent sessions from the agent and channel name
([#3028](#3028))
([`f2fe3b63c`](f2fe3b6))
- feat(git): use agent display name as git author name
([#3040](#3040))
([`18eef633d`](18eef63))
- fix(deps): bump nostr to 0.44.6 for RUSTSEC-2026-0216 (NIP-44 remote
DoS) ([#3135](#3135))
([`31e2de196`](31e2de1))
- fix(desktop): read the newest pair-scoped harness log
([#3134](#3134))
([`654f38490`](654f384))
- feat(desktop): handle project work from Inbox
([#3117](#3117))
([`c5c4f390b`](c5c4f39))
- fix(desktop): clarify identity key button when key exists
([#2357](#2357))
([`87b3fcd3c`](87b3fcd))
- Restore Goose and Buzz Agent to onboarding harness selection
([#2731](#2731))
([`7fc0cc82d`](7fc0cc8))
- fix(desktop): render rich project work item content
([#3100](#3100))
([`afb272bb7`](afb272b))
- feat(acp): bring your own harness (BYOH) — generic ACP runtime seam +
settings gallery ([#2773](#2773))
([`95fdf9788`](95fdf97))
- feat(desktop): use collective mesh routing for Auto
([#2825](#2825))
([`16d4ec335`](16d4ec3))
- fix(desktop): strip legacy baked team instructions from stored prompts
([#3035](#3035))
([`aee631448`](aee6314))
- feat(agents): lower default agent parallelism from 24 to 10
([#3038](#3038))
([`5d8ede446`](5d8ede4))
- Polish community rail and mobile pairing
([#2972](#2972))
([`e6c90bb7c`](e6c90bb))
- fix(desktop): remove bundled libsystemd from AppImage
([#2353](#2353))
([`a31fc4d2f`](a31fc4d))
- fix(desktop): make agent definition authoritative for
model/provider/prompt ([#1968](#1968))
([`8c0e8cb16`](8c0e8cb))
- chore(desktop): delete dead persona catalog UI cluster
([#2886](#2886))
([`8e67cf399`](8e67cf3))
- fix(desktop): surface install failures hidden by curl-pipe exit codes
([#2892](#2892))
([`166c6655e`](166c665))
- Refactor managed-agent runtime into cohesive modules
([#2974](#2974))
([`74b63e184`](74b63e1))
- fix(desktop): make Linux AppImage GStreamer work on non-Debian distros
([#2176](#2176))
([`cc6c4d347`](cc6c4d3))
- refactor(desktop): remove Agent directory section from Agents page
([#2290](#2290))
([`5d1233e84`](5d1233e))
- fix(desktop): enable arboard Wayland backend so Linux copies reach the
Wayland clipboard ([#2904](#2904))
([`ab7aa8b12`](ab7aa8b))
- fix(desktop): supervise and re-arm relay-mesh runtime
([#2823](#2823))
([`aa51dab9d`](aa51dab))
- fix(agents): run live Databricks discovery instead of the fallback
list ([#2890](#2890))
([`8eb6e3eb6`](8eb6e3e))
- fix(desktop): retire prepend mode on every reader wheel
([#2913](#2913))
([`07d0265cf`](07d0265))
- fix(desktop): consolidate prepend scroll correction
([#2855](#2855))
([`25e7864b3`](25e7864))
- fix(desktop): track concurrent agent turns up to the harness maximum
([#2882](#2882))
([`20bff5910`](20bff59))
- fix(relay): preserve reconnect backoff
([#2759](#2759))
([`499c5d349`](499c5d3))
- refactor(relay): expose reconnect timing policy
([#2310](#2310))
([`2f0041595`](2f00415))
- fix(desktop): clear stale working badges on agent stop/restart
([#2803](#2803))
([`a64cc71f6`](a64cc71))
- fix(desktop): surface agent rename relay profile sync failure as a
warning toast ([#2279](#2279))
([`5e3d2e484`](5e3d2e4))
- fix(discovery): inject PATH into Codex adapter planning
([#2767](#2767))
([`6ab3835f3`](6ab3835))

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

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
cameronhotchkies pushed a commit to cameronhotchkies/buzz that referenced this pull request Jul 28, 2026
…y-to-env

* origin/main: (22 commits)
  Polish mobile message and search layouts (block#3121)
  Add mobile message image galleries (block#3312)
  chore(release): release Buzz Desktop version 0.5.0 (block#3213)
  feat(relay): make Postgres pool size configurable, default 50 (block#3191)
  Publish symbol-bearing debug relay images (block#3250)
  feat(tracing): add datastore tracing plumbing (block#2760)
  fix(buzz-acp): accept id-keyed config options when resolving model switch (block#2795)
  fix(desktop): probe legacy Goose install dir on Windows (block#3248)
  refactor(desktop): extract install command execution into install_exec (block#3251)
  Polish composer activity layout and transitions (block#3151)
  feat(invites): add use-limited invite links (block#3141)
  fix(node): bump Buzz-supplied Node runtimes past OpenClaw's >=24.15.0 floor (block#3218)
  fix(desktop): preserve thread anchor through layout reflow (block#3212)
  feat(search): parse from:/in:/after:/before: and pass them in the filter (block#2871)
  fix(desktop): fetch join policies through native networking (block#2862)
  fix(desktop): republish agent identity records when a persona rename propagates (block#2607)
  fix(desktop): keep project Inbox previews compact (block#3193)
  Inbox refactor (block#2045)
  Fix composer selection formatting and drop overlay (block#3172)
  Refine pending message status (block#3153)
  ...

Signed-off-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz>
Co-authored-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants