diff --git a/crates/buzz-db/src/lib.rs b/crates/buzz-db/src/lib.rs index 6461eb74083..c71255833d9 100644 --- a/crates/buzz-db/src/lib.rs +++ b/crates/buzz-db/src/lib.rs @@ -1335,54 +1335,6 @@ impl Db { Ok(result.rows_affected()) } - /// Mints a v2 use-limited relay invite. The plaintext code is returned - /// exactly once; only its SHA-256 hash is persisted. - /// - /// `max_uses` is `None` for unlimited or `Some(1..=10000)`. - /// `ttl_secs` must be in the shared invite lifetime range. - #[datastore_span(name = "mint_relay_invite", system = "postgresql")] - pub async fn mint_relay_invite( - &self, - community: CommunityId, - created_by: &str, - ttl_secs: u64, - max_uses: Option, - ) -> Result { - relay_invite::mint_relay_invite(&self.pool, community, created_by, ttl_secs, max_uses).await - } - - /// Delete one bounded batch of invites expired before `cutoff`. - #[datastore_span(name = "reap_expired_relay_invites", system = "postgresql")] - pub async fn reap_expired_relay_invites( - &self, - cutoff: chrono::DateTime, - ) -> Result { - relay_invite::reap_expired_relay_invites(&self.pool, cutoff).await - } - - /// Atomically claims a v2 relay invite. The full redemption (membership - /// insert, policy evidence, use_count increment) runs in one PostgreSQL - /// transaction with `FOR UPDATE` on the invite row. - /// - /// `token_hash` is the SHA-256 of the presented v2 code (32 bytes). - #[datastore_span(name = "claim_relay_invite", system = "postgresql")] - pub async fn claim_relay_invite( - &self, - community: CommunityId, - token_hash: &[u8; 32], - claimer_pubkey: &str, - policy_version: Option<&str>, - ) -> Result { - relay_invite::claim_relay_invite( - &self.pool, - community, - token_hash, - claimer_pubkey, - policy_version, - ) - .await - } - /// Sidecar an accepted product-feedback event, idempotent by event id. #[datastore_span(name = "insert_product_feedback", system = "postgresql")] pub async fn insert_product_feedback( diff --git a/crates/buzz-db/src/relay_invite.rs b/crates/buzz-db/src/relay_invite.rs index 14331b022f5..1424829933f 100644 --- a/crates/buzz-db/src/relay_invite.rs +++ b/crates/buzz-db/src/relay_invite.rs @@ -21,11 +21,12 @@ use buzz_core::invite::{ encode_v2_code, hash_v2_code, MAX_INVITE_TTL_SECS, MAX_INVITE_USES, MIN_INVITE_TTL_SECS, V2_SECRET_LEN, }; +use buzz_datastore_tracing::datastore_span; use chrono::{DateTime, Utc}; use sqlx::{PgPool, Row as _}; use crate::error::Result; -use crate::CommunityId; +use crate::{CommunityId, Db}; /// Outcome of a v2 invite claim. Expected invalid/expired/exhausted states are /// typed variants so the relay layer can map them to distinct HTTP responses @@ -380,6 +381,53 @@ pub async fn claim_relay_invite( }) } +impl Db { + /// Mints a v2 use-limited relay invite. The plaintext code is returned + /// exactly once; only its SHA-256 hash is persisted. + /// + /// `max_uses` is `None` for unlimited or `Some(1..=10000)`. + /// `ttl_secs` must be in the shared invite lifetime range. + #[datastore_span(name = "mint_relay_invite", system = "postgresql")] + pub async fn mint_relay_invite( + &self, + community: CommunityId, + created_by: &str, + ttl_secs: u64, + max_uses: Option, + ) -> Result { + mint_relay_invite(&self.pool, community, created_by, ttl_secs, max_uses).await + } + + /// Delete one bounded batch of invites expired before `cutoff`. + #[datastore_span(name = "reap_expired_relay_invites", system = "postgresql")] + pub async fn reap_expired_relay_invites(&self, cutoff: DateTime) -> Result { + reap_expired_relay_invites(&self.pool, cutoff).await + } + + /// Atomically claims a v2 relay invite. The full redemption (membership + /// insert, policy evidence, use_count increment) runs in one PostgreSQL + /// transaction with `FOR UPDATE` on the invite row. + /// + /// `token_hash` is the SHA-256 of the presented v2 code (32 bytes). + #[datastore_span(name = "claim_relay_invite", system = "postgresql")] + pub async fn claim_relay_invite( + &self, + community: CommunityId, + token_hash: &[u8; 32], + claimer_pubkey: &str, + policy_version: Option<&str>, + ) -> Result { + claim_relay_invite( + &self.pool, + community, + token_hash, + claimer_pubkey, + policy_version, + ) + .await + } +} + #[cfg(test)] mod tests { use super::*;