revert: remove backend changes, keep desktop-only fix

Strip sprout-db and sprout-relay changes per Wes's direction. The
backend already supports bot role via kind:9000 ON CONFLICT — no
relay-side changes needed. Bot classification and respond-to
visibility fixes are entirely desktop-side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Wes
2026-05-14 13:36:54 -07:00
parent 69e91987d7
commit 02a3a0861a
5 changed files with 6 additions and 78 deletions

View File

@@ -487,26 +487,6 @@ pub async fn remove_member(
Ok(())
}
/// Upgrade all active "member" role entries for `pubkey` to "bot" across all channels.
/// Returns the number of rows updated. This is used when an agent's owner relationship
/// is first materialized (NIP-OA auth) to fix pre-existing memberships that were
/// incorrectly assigned the "member" role.
pub async fn upgrade_member_to_bot(pool: &PgPool, pubkey: &[u8]) -> Result<u64> {
let result = sqlx::query(
r#"
UPDATE channel_members
SET role = 'bot'::member_role
WHERE pubkey = $1
AND role = 'member'::member_role
AND removed_at IS NULL
"#,
)
.bind(pubkey)
.execute(pool)
.await?;
Ok(result.rows_affected())
}
/// Returns `true` if the given pubkey is an active member of the channel.
pub async fn is_member(pool: &PgPool, channel_id: Uuid, pubkey: &[u8]) -> Result<bool> {
let row = sqlx::query(

View File

@@ -406,11 +406,6 @@ impl Db {
channel::remove_member(&self.pool, channel_id, pubkey, actor_pubkey).await
}
/// Upgrade all active "member" role entries for `pubkey` to "bot" across all channels.
pub async fn upgrade_member_to_bot(&self, pubkey: &[u8]) -> Result<u64> {
channel::upgrade_member_to_bot(&self.pool, pubkey).await
}
/// Returns `true` if the pubkey is an active member.
pub async fn is_member(&self, channel_id: Uuid, pubkey: &[u8]) -> Result<bool> {
channel::is_member(&self.pool, channel_id, pubkey).await
@@ -593,11 +588,6 @@ impl Db {
user::is_agent_owner(&self.pool, target_pubkey, actor_pubkey).await
}
/// Check whether `pubkey` is a known agent (has `agent_owner_pubkey` set).
pub async fn is_agent(&self, pubkey: &[u8]) -> Result<bool> {
user::is_agent(&self.pool, pubkey).await
}
/// Set the channel_add_policy for a user.
pub async fn set_channel_add_policy(&self, pubkey: &[u8], policy: &str) -> Result<()> {
user::set_channel_add_policy(&self.pool, pubkey, policy).await

View File

@@ -342,18 +342,6 @@ pub async fn is_agent_owner(
Ok(row.unwrap_or(false))
}
/// Check whether `pubkey` is a known agent (has `agent_owner_pubkey` set).
/// Returns `false` if the pubkey doesn't exist in the users table.
pub async fn is_agent(pool: &PgPool, pubkey: &[u8]) -> Result<bool> {
let row = sqlx::query_scalar::<_, bool>(
"SELECT agent_owner_pubkey IS NOT NULL FROM users WHERE pubkey = $1",
)
.bind(pubkey)
.fetch_optional(pool)
.await?;
Ok(row.unwrap_or(false))
}
/// Set the channel_add_policy for a user.
/// Returns an error if the pubkey is not found (rows_affected == 0).
/// Returns an error if `policy` is not one of the valid ENUM values.

View File

@@ -212,32 +212,6 @@ pub async fn handle_auth(event: nostr::Event, conn: Arc<ConnectionState>, state:
);
}
}
// If we confirmed this is an agent, fix any existing channel
// memberships that have "member" role instead of "bot". The query
// is a no-op (0 rows) once all roles are correct.
if auth_ctx.agent_owner_pubkey.is_some() {
let agent_bytes = pubkey.serialize().to_vec();
match state.db.upgrade_member_to_bot(&agent_bytes).await {
Ok(0) => {}
Ok(n) => {
info!(
conn_id = %conn_id,
agent = %pubkey.to_hex(),
count = n,
"upgraded agent member roles to bot"
);
}
Err(e) => {
warn!(
conn_id = %conn_id,
agent = %pubkey.to_hex(),
error = %e,
"failed to upgrade agent member roles"
);
}
}
}
}
info!(conn_id = %conn_id, pubkey = %pubkey.to_hex(), "NIP-42 auth successful");

View File

@@ -1223,19 +1223,15 @@ async fn handle_join_request(event: &Event, state: &Arc<AppState>) -> anyhow::Re
return Ok(());
}
// Detect agents: if the joining pubkey has an agent_owner_pubkey set in the
// users table, assign them the "bot" role instead of "member". This ensures
// that agents are correctly classified for all users, not just the bot owner.
let role = if state.db.is_agent(&actor_bytes).await.unwrap_or(false) {
sprout_db::channel::MemberRole::Bot
} else {
sprout_db::channel::MemberRole::Member
};
// Add as member (idempotent — add_member handles duplicates).
state
.db
.add_member(channel_id, &actor_bytes, role, None)
.add_member(
channel_id,
&actor_bytes,
sprout_db::channel::MemberRole::Member,
None,
)
.await?;
state.invalidate_membership(channel_id, &actor_bytes);