Skip to main content

atproto_tap/
lib.rs

1//! TAP (Trusted Attestation Protocol) service consumer for AT Protocol.
2//!
3//! This crate provides a client for consuming events from a TAP service,
4//! which delivers filtered, verified AT Protocol repository events.
5//!
6//! # Overview
7//!
8//! TAP is a single-tenant service that subscribes to an AT Protocol Relay and
9//! outputs filtered, verified events. Key features include:
10//!
11//! - **Verified Events**: MST integrity checks and signature verification
12//! - **Automatic Backfill**: Historical events delivered with `live: false`
13//! - **Repository Filtering**: Track specific DIDs or collections
14//! - **Acknowledgment Protocol**: At-least-once delivery semantics
15//!
16//! # Quick Start
17//!
18//! ```ignore
19//! use atproto_tap::{connect_to, TapEvent};
20//! use tokio_stream::StreamExt;
21//!
22//! #[tokio::main]
23//! async fn main() {
24//!     let mut stream = connect_to("localhost:2480");
25//!
26//!     while let Some(result) = stream.next().await {
27//!         match result {
28//!             Ok(event) => match event.as_ref() {
29//!                 TapEvent::Record { record, .. } => {
30//!                     println!("{} {} {}", record.action, record.collection, record.did);
31//!                 }
32//!                 TapEvent::Identity { identity, .. } => {
33//!                     println!("Identity: {} = {}", identity.did, identity.handle);
34//!                 }
35//!             },
36//!             Err(e) => eprintln!("Error: {}", e),
37//!         }
38//!     }
39//! }
40//! ```
41//!
42//! # Using with `tokio::select!`
43//!
44//! The stream integrates naturally with Tokio's select macro:
45//!
46//! ```ignore
47//! use atproto_tap::{connect, TapConfig};
48//! use tokio_stream::StreamExt;
49//! use tokio::signal;
50//!
51//! #[tokio::main]
52//! async fn main() {
53//!     let config = TapConfig::builder()
54//!         .hostname("localhost:2480")
55//!         .admin_password("secret")
56//!         .build();
57//!
58//!     let mut stream = connect(config);
59//!
60//!     loop {
61//!         tokio::select! {
62//!             Some(result) = stream.next() => {
63//!                 // Process event
64//!             }
65//!             _ = signal::ctrl_c() => {
66//!                 break;
67//!             }
68//!         }
69//!     }
70//! }
71//! ```
72//!
73//! # Management API
74//!
75//! Use [`TapClient`] to manage tracked repositories:
76//!
77//! ```ignore
78//! use atproto_tap::TapClient;
79//!
80//! let client = TapClient::new("localhost:2480", Some("password".to_string()));
81//!
82//! // Add repositories to track
83//! client.add_repos(&["did:plc:xyz123"]).await?;
84//!
85//! // Check service health
86//! if client.health().await? {
87//!     println!("TAP service is healthy");
88//! }
89//! ```
90//!
91//! # Memory Efficiency
92//!
93//! This crate is optimized for high-throughput event processing:
94//!
95//! - **Arc-wrapped events**: Events are shared via `Arc` for zero-cost sharing
96//! - **CompactString**: Small strings use inline storage (no heap allocation)
97//! - **`Box<str>`**: Immutable strings without capacity overhead
98//! - **RawValue**: Record payloads are lazily parsed on demand
99//! - **Pre-allocated buffers**: Ack messages avoid per-message allocations
100
101#![forbid(unsafe_code)]
102#![warn(missing_docs)]
103
104mod client;
105mod config;
106mod connection;
107mod errors;
108mod events;
109mod stream;
110
111// Re-export public types
112pub use atproto_identity::model::{Document, Service, VerificationMethod};
113#[allow(deprecated)]
114pub use client::RepoStatus;
115pub use client::{RepoInfo, RepoState, TapClient};
116pub use config::{TapConfig, TapConfigBuilder};
117pub use errors::TapError;
118pub use events::{
119    IdentityEvent, IdentityStatus, RecordAction, RecordEvent, TapEvent, extract_event_id,
120};
121pub use stream::{TapStream, connect, connect_to};