fix(desktop): retry agent profile sync once after relay_membership_required 403 - #4088
Open
iroiro147 wants to merge 1 commit into
Open
fix(desktop): retry agent profile sync once after relay_membership_required 403#4088iroiro147 wants to merge 1 commit into
iroiro147 wants to merge 1 commit into
Conversation
…quired 403
On a self-hosted relay with BUZZ_REQUIRE_RELAY_MEMBERSHIP=true, the
automatic relay_members grant for a brand-new agent pubkey lands
asynchronously — typically within ~1s of the first connection attempt.
The desktop client's initial kind:0 profile publish therefore races the
grant, and a closed relay rejects the first POST /events with a 403
{"error":"relay_membership_required","message":"You must be a
relay member to access this relay"} even though the same publish
succeeds moments later. The customer-visible result is the
"Could not sync the agent's profile metadata: relay returned 403"
dialog on the happy-path Create Agent flow.
Make sync_managed_agent_profile retry the POST exactly once after a
500ms delay when (and only when) the relay returned 403 with
relay_membership_required in the body, and surface the original
error unchanged for all other failure shapes. One attempt is enough —
if the grant still hasn't landed after ~500ms the pod's membership
backfill is genuinely wedged and a retry loop won't help.
Receipts:
- Fixes block#3888.
- 4 new unit tests on the error-summarize helper cover the
membership-body, error-only, non-JSON, and empty-body shapes.
- Existing egress_guard boundary test
(boundary_sync_managed_agent_profile_blocks_ncryptsec) still passes.
- cargo check / cargo clippy -D warnings / cargo test --lib targeted
(summarize_relay 4/4 + egress_guard 1/1) all green on
buzz-desktop v0.5.3 (Tauri v2, Rust 1.x).
Signed-off-by: Sarthak Singh <sarthak.singh@juspay.in>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3888.
On a self-hosted relay with
BUZZ_REQUIRE_RELAY_MEMBERSHIP=true, the automaticrelay_membersgrant for a brand-new agent pubkey lands asynchronously — typically within ~1 s of the first connection attempt. The desktop client's initial kind:0 profile publish therefore races the grant, and a closed relay rejects the firstPOST /eventswith a 403{"error":"relay_membership_required","message":"You must be a relay member to access this relay"}even though the same publish succeeds moments later.The reporter verified directly against the relay's Postgres that:
relay_membersrow for the same pubkey is inserted at T+~130 ms–1 s,The visible result on the happy-path Create Agent flow is the
"Could not sync the agent's profile metadata: relay returned 403 Forbidden: You must be a relay member to access this relay"dialog, even though the agent was created and (by the time the user reads the dialog) is already a relay member.Change
sync_managed_agent_profilenow retries the POST exactly once — after a 500 ms delay — when (and only when) the relay returned a 403 whose body containsrelay_membership_required. All other 4xx/5xx failures surface the original error unchanged, and a fully denied (never-member) relay still errors exactly as before, just ~500 ms slower on the first attempt.One retry is enough: if the grant still hasn't landed after ~500 ms, the pod's membership backfill is genuinely wedged and a retry loop won't help. This is a small, deliberate defense against a specific, real race the reporter reproduced twice — not a general retry policy.
Because the fix lives inside
sync_managed_agent_profile, every caller benefits:commands/agents.rs(the reported path),commands/agent_models.rs,commands/personas/snapshot/import.rs,commands/personas/update.rs,commands/agents_profile.rs,commands/team_snapshot.rs— no caller changes needed.The body-builder also gained a small
summarize_relay_errorhelper that mirrors the "real relay error" branch of the existingrelay_error_message, but takes a pre-read body string. That's just so the new retry path can consume the response body once and reuse the same message format;relay_error_message(which still owns itsreqwest::Response) is untouched.Test plan
summarize_relay_errorhelper: membership-required JSON, error-only JSON, non-JSON body, and empty body shapes.egress_guard::tests::boundary_sync_managed_agent_profile_blocks_ncryptsecboundary test (which callssync_managed_agent_profiledirectly with a fake secret-bearing payload) still passes — the function still rejectsncryptsecbody bytes before any network I/O.cargo check --lib·cargo clippy --lib --all-targets -- -D warnings·cargo test --lib summarize_relayall green onbuzz-desktopv0.5.3 (Tauri v2).Not end-to-end-verified against a real self-hosted closed relay (would require a two-pod relay + a
BUZZ_REQUIRE_RELAY_MEMBERSHIP=trueconfig + a frozen Postgres), but the behavior change is fully contained in an existing async fn whose error / success surface is unit-tested, and the new retry is gated on the exact 403 body shape the relay emits (crates/buzz-relay/src/api/mod.rs:136).Oval-known risks
0..2and breaks onis_membership_403 && attempt == 0continuing once, otherwise returning the final error.