Files
buzz/crates/buzz-db/src/lib.rs
seiler 1b81b01b01 Add durable live member authorization checks
Signed-off-by: seiler <seiler@squareup.com>
Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit 92f13229ed3038d63f2a2d9c889bfd4c212e38e2)
Signed-off-by: Brad Seiler <seiler@squareup.com>
2026-11-04 17:29:19 -05:00

134 lines
5.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#![deny(unsafe_code)]
#![warn(missing_docs)]
//! buzz-db — Postgres event store for Buzz.
//!
//! ## Design invariants
//! - AUTH events (kind 22242) are never stored — they carry bearer tokens.
//! - Ephemeral events (20000–29999) are never stored — Redis pub/sub only.
//! - Events table is partitioned by month on `created_at`.
//! - No FK references to partitioned tables.
//! - Uses `sqlx::query()` (runtime) not `sqlx::query!()` (compile-time).
//!
//! ## Runtime and store ownership
//! Database runtime infrastructure and domain persistence are physically
//! separated behind this crate-root compatibility facade:
//!
//! - Runtime concerns own pool construction, writer/replica routing,
//! transactions, sessions, metrics, health support, and migrations.
//! - Store concerns own domain-specific SQL, row mapping, locking, mutation
//! rules, indexes, and focused persistence tests.
//!
//! Existing crate-root modules, records, and [`Db`] methods remain the public
//! API. The internal `runtime` and `store` namespaces are not public APIs.
/// Wrap `$retire`, an `UPDATE`/`DELETE` on `events` that retires a
/// coordinate's previous head, so the same statement drops those rows' mention
/// index entries. Mention-index reads (`#p` filters and feeds) never return a
/// retired row, so its mention rows are dead weight they must walk and
/// discard: one per member for every kind:39002 roster republish. `$1` must
/// bind the community.
///
/// The three replacement paths that index mentions (NIP-33 parameterized,
/// addressable, and the relay's member snapshot) go through this, so a head
/// and its mention rows leave together on those paths.
macro_rules! superseded_with_mentions_sql {
($retire:literal) => {
concat!(
"WITH superseded AS (",
$retire,
" RETURNING id) \
DELETE FROM event_mentions mention USING superseded \
WHERE mention.community_id = $1 AND mention.event_id = superseded.id"
)
};
}
mod runtime;
mod store;
/// Database error types.
pub mod error;
#[cfg(test)]
mod test_support;
pub use runtime::{
insert_mentions, migration, replica_fence, AdmittedTx, ColdStartError, Db, DbConfig,
DbConnectionOutcome, DbConnectionStep, DbPoolRole, DbPoolStats, DbReadinessOutcome,
ReadSession,
};
/// Valid low-cardinality `(pool_role, operation)` pairs for pool-acquisition telemetry.
pub const DB_POOL_ACQUIRE_VALID_PAIRS: [(&str, &str); 12] =
runtime::observability::POOL_ACQUIRE_VALID_PAIRS;
/// Raw Prometheus series ceiling per relay pod for the operation-aware contract.
pub const DB_POOL_ACQUIRE_RAW_SERIES_PER_POD: usize =
runtime::observability::POOL_ACQUIRE_RAW_SERIES_PER_POD;
/// Valid database connection role/step pairs with a start counter.
pub const DB_CONNECTION_STARTED_STEPS: [(DbPoolRole, DbConnectionStep); 4] =
runtime::CONNECTION_STARTED_STEPS;
/// Valid database connection role/step pairs with a duration histogram.
pub const DB_CONNECTION_DURATION_STEPS: [(DbPoolRole, DbConnectionStep); 4] =
runtime::CONNECTION_DURATION_STEPS;
/// Valid database connection role/step/outcome terminal combinations.
pub const DB_CONNECTION_TERMINALS: [(DbPoolRole, DbConnectionStep, DbConnectionOutcome); 15] =
runtime::CONNECTION_TERMINALS;
/// Raw Prometheus series ceiling per pod for connection-step telemetry.
pub const DB_CONNECTION_RAW_SERIES_PER_POD: usize = runtime::CONNECTION_RAW_SERIES_PER_POD;
pub(crate) use runtime::{
begin_community_event_write_transaction,
begin_community_event_write_transaction_with_legacy_metrics, begin_community_sweep_transaction,
begin_community_write_transaction, insert_mentions_in_transaction, observability, route_proof,
sweep_admitted_communities, ReadSessionInner, RouteDecision, RoutePredicate,
};
pub use store::{
admin_moderation, allowlist, api_token, archived_identities, artifact, artifact_sync, channel,
channel_members, community, community_auth, deletion, dm, entity_deletion, event, feed,
git_repo, live_authorization, moderation, nip_fi_binding, operator_listener, partition,
personal_read, product_feedback, push, reaction, read_state, relay_admin_actions, relay_invite,
relay_members, relay_operators, reminder, replaceable, storage_accounting, thread,
thread_window, usage, user, user_deletion, user_deletion_fences, workflow,
};
pub use allowlist::AllowlistEntry;
pub use api_token::{ApiTokenRecord, TokenSummary};
pub use community::{
ArchivedCommunityRecord, CommunityRecord, CreateCommunityWithOwnerResult,
CreatedCommunityRecord, EnsuredCommunityRecord, OwnedCommunityRecord, UnarchiveCommunityResult,
UnarchivedCommunityRecord,
};
pub use error::{DbError, Result};
pub use event::{ChannelHeadPrecondition, ChannelHeadWriteStatus, DeletionTarget};
pub use event::{EventQuery, DEFAULT_MAX_PAGE_LIMIT};
pub use live_authorization::{LiveAuthorizationState, LiveAuthorizationTarget};
pub use nip_fi_binding::{NipFiBindingRecord, NipFiUnbind, RowCapExceeded};
pub use reaction::ReactionEventInsertOutcome;
pub use reminder::DueReminder;
pub use store::{ArtifactSnapshot, SnapshotDenied};
pub use usage::SessionLeader;
/// A value read from the database, with when its reading connection was
/// checked out of the pool.
///
/// The statement that produced `value` started after `read_at`, so its
/// snapshot is no older than `read_at`. A cache that serves `value` for a
/// bound after `read_at` is never staler than that bound, however long the
/// read waited for a connection.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ReadAt<T> {
/// The value as read.
pub value: T,
/// When the connection that read `value` was checked out.
pub read_at: std::time::Instant,
}
use buzz_core::CommunityId;
/// Durable NIP-FI verified-profile projection state.
pub use store::verified_profiles;