Files
buzz/crates/buzz-core/src/lib.rs
T
d500c2d5cf feat(invites): add use-limited invite links (#3141)
## Summary

- add database-backed v2 invite links with optional maximum-use limits
and atomic final-slot redemption
- preserve v1 invite compatibility while adding
exhausted/expired/invalid client handling across desktop, web, and
mobile
- emit structured claim-outcome logs with community, invite ID, outcome,
maximum uses, and post-claim count

## Verification

- `cargo fmt --all -- --check`
- `cargo test -p buzz-db` (85 passed, 134 Postgres-dependent ignored)
- `cargo clippy -p buzz-db --all-targets -- -D warnings`
- desktop `npm run typecheck`
- push hook: desktop checks/tests, desktop Tauri tests, Rust tests, and
branch-skew passed
- Postgres integration tests were previously reviewed green at the
pre-rebase tree; local rerun on this session was unavailable because
Postgres/Docker were not running
- mobile push-hook check could not start because Flutter is unavailable
locally

---------

Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
Co-authored-by: npub1c4alndp82zyt9veaklm5d965quss79vlhk9awv7qu5erwhmf42qqlvc25c <c57bf9b4275088b2b33db7f746975407210f159fbd8bd733c0e532375f69aa80@buzz.block.builderlab.xyz>
Co-authored-by: npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc <5288f082d91aff2de5bc8be23fbfa01ca2e3859cac57a91b7a3fa9f12349505c@buzz.block.builderlab.xyz>
Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
2026-07-27 15:19:39 -07:00

78 lines
2.7 KiB
Rust

#![deny(unsafe_code)]
#![warn(missing_docs)]
//! `buzz-core` — zero-I/O foundation types for the Buzz relay.
//!
//! Provides [`StoredEvent`], filter matching, kind constants, and event
//! verification. All other Buzz crates depend on this one.
/// NIP-AM: Agent Turn Metric — payload type and encrypt/decrypt helpers.
pub mod agent_turn_metric;
/// Channel and membership enums shared across crates.
pub mod channel;
/// NIP-AE Agent Engrams — slug grammar, conversation key, d-tag derivation,
/// body parse/serialize, envelope build/validate, head selection.
pub mod engram;
/// Relay-side error types.
pub mod error;
/// Relay-side event wrapper with verification tracking.
pub mod event;
/// NIP-01 subscription filter matching.
pub mod filter;
/// Git permission types — ref patterns, protection rules, policy evaluation.
pub mod git_perms;
/// Shared invite-link contract constants.
pub mod invite;
/// Buzz kind number registry — custom event type constants.
pub mod kind;
/// Network utilities — SSRF-safe IP classification.
pub mod network;
/// Agent observer frame helpers.
pub mod observer;
/// NIP-AB device pairing — crypto primitives, message types, and errors.
pub mod pairing;
/// Presence status types shared across crates.
pub mod presence;
/// Canonical relay runtime identities.
pub mod relay;
/// Tenant identity — the server-resolved community key carried on scoped paths.
pub mod tenant;
/// Schnorr signature and event ID verification.
pub mod verification;
pub use error::VerificationError;
pub use event::StoredEvent;
pub use nostr::{Event, EventId, Filter, Keys, Kind, PublicKey};
pub use presence::PresenceStatus;
pub use tenant::{normalize_host, CommunityId, TenantContext};
pub use verification::verify_event;
#[cfg(any(test, feature = "test-utils"))]
/// Test helper utilities for creating events and stored events.
pub mod test_helpers {
use crate::StoredEvent;
use chrono::Utc;
use nostr::{EventBuilder, Keys, Kind};
/// Create a signed test event with the given kind and random keys.
pub fn make_event(kind: Kind) -> nostr::Event {
let keys = Keys::generate();
EventBuilder::new(kind, "test")
.tags([])
.sign_with_keys(&keys)
.expect("sign")
}
/// Create a signed test event with the given keys and kind.
pub fn make_event_with_keys(keys: &Keys, kind: Kind) -> nostr::Event {
EventBuilder::new(kind, "test")
.tags([])
.sign_with_keys(keys)
.expect("sign")
}
/// Create a [`StoredEvent`] wrapper around a test event.
pub fn make_stored_event(kind: Kind, channel_id: Option<uuid::Uuid>) -> StoredEvent {
StoredEvent::with_received_at(make_event(kind), Utc::now(), channel_id, true)
}
}