From 20835e02329d057e726be23c81a6941fb38bbe18 Mon Sep 17 00:00:00 2001 From: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz> Date: Fri, 25 Sep 2026 14:16:43 -0400 Subject: [PATCH] fix(channels): require agent membership for rename delegation Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz> --- crates/buzz-relay/src/handlers/channel_authz.rs | 9 +++++---- crates/buzz-relay/src/handlers/side_effects.rs | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/buzz-relay/src/handlers/channel_authz.rs b/crates/buzz-relay/src/handlers/channel_authz.rs index eeb7621abd..c7f3fca55a 100644 --- a/crates/buzz-relay/src/handlers/channel_authz.rs +++ b/crates/buzz-relay/src/handlers/channel_authz.rs @@ -77,11 +77,11 @@ pub fn is_sole_owner(members: &[MemberRecord], pubkey: &[u8]) -> bool { pub fn can_edit_privileged_metadata( actor_role: Option<&str>, actor_owns_owner_agent: bool, - actor_is_owned_by_elevated_member: bool, + actor_is_owned_by_channel_owner: bool, ) -> bool { matches!(actor_role, Some("owner" | "admin")) || actor_owns_owner_agent - || actor_is_owned_by_elevated_member + || (actor_role.is_some() && actor_is_owned_by_channel_owner) } /// Decide whether `actor` may remove themselves from the channel. @@ -655,8 +655,9 @@ mod tests { } #[test] - fn owner_agent_may_edit_privileged_metadata_for_its_human_owner() { - assert!(can_edit_privileged_metadata(None, false, true)); + fn owner_agent_metadata_authority_requires_channel_membership() { + assert!(can_edit_privileged_metadata(Some("bot"), false, true)); + assert!(!can_edit_privileged_metadata(None, false, true)); } /// The wire contract: these strings reach NIP-29 clients verbatim, and the diff --git a/crates/buzz-relay/src/handlers/side_effects.rs b/crates/buzz-relay/src/handlers/side_effects.rs index 866083c28b..394cf65782 100644 --- a/crates/buzz-relay/src/handlers/side_effects.rs +++ b/crates/buzz-relay/src/handlers/side_effects.rs @@ -443,7 +443,7 @@ async fn actor_owns_any_owner_agent( /// Returns `true` if `actor_bytes` is an agent whose owning human is an active /// owner member. This grants an owner's managed agent the same metadata -/// authority without requiring the agent itself to be added to the channel. +/// authority only when the agent is itself an active channel member. async fn actor_is_owned_by_channel_owner( state: &Arc, community_id: buzz_core::CommunityId, @@ -696,7 +696,7 @@ pub async fn validate_admin_event( .await? }; let actor_is_owned_by_channel_owner = - if actor_role.is_some() || actor_owns_owner_agent { + if actor_role.is_none() || actor_owns_owner_agent { false } else { actor_is_owned_by_channel_owner(