A library for ATProtocol identities.
1# atproto-record
2
3Utilities for working with AT Protocol records.
4
5## Overview
6
7A Rust library for working with AT Protocol records, providing AT-URI parsing, TID generation, datetime formatting, and CID generation. Built on IPLD DAG-CBOR serialization for deterministic content addressing.
8
9## Features
10
11- **AT-URI parsing**: Parse and validate AT Protocol URIs (at://authority/collection/record_key) with robust error handling
12- **TID generation**: Timestamp-based identifiers for AT Protocol records with microsecond precision
13- **CID generation**: Content Identifier generation using DAG-CBOR serialization and SHA-256 hashing
14- **DateTime utilities**: RFC 3339 datetime serialization with millisecond precision for consistent timestamp handling
15- **Typed records**: Type-safe record handling with lexicon type validation
16- **Bytes handling**: Base64 encoding/decoding for binary data in AT Protocol records
17- **Structured errors**: Type-safe error handling following project conventions with detailed error messages
18
19## CLI Tools
20
21The following command-line tool is available when built with the `clap` feature:
22
23- **`atproto-record-cid`**: Generate CID (Content Identifier) for AT Protocol records from JSON input
24
25## Library Usage
26
27### Generating CIDs
28
29```rust
30use serde_json::json;
31use cid::Cid;
32use sha2::{Digest, Sha256};
33use multihash::Multihash;
34
35// Serialize a record to DAG-CBOR and generate its CID
36let record = json!({
37 "$type": "app.bsky.feed.post",
38 "text": "Hello world!",
39 "createdAt": "2024-01-01T00:00:00.000Z"
40});
41
42let dag_cbor_bytes = serde_ipld_dagcbor::to_vec(&record)?;
43let hash = Sha256::digest(&dag_cbor_bytes);
44let multihash = Multihash::wrap(0x12, &hash)?;
45let cid = Cid::new_v1(0x71, multihash);
46
47println!("Record CID: {}", cid);
48```
49
50### Generating TIDs
51
52```rust
53use atproto_record::tid::Tid;
54
55// Generate a new timestamp-based identifier
56let tid = Tid::new();
57println!("TID: {}", tid); // e.g., "3l2k4j5h6g7f8d9s"
58
59// TIDs are sortable by creation time
60let tid1 = Tid::new();
61std::thread::sleep(std::time::Duration::from_millis(1));
62let tid2 = Tid::new();
63assert!(tid1 < tid2);
64```
65
66### AT-URI Parsing
67
68```rust
69use atproto_record::aturi::ATURI;
70use std::str::FromStr;
71
72// Parse an AT-URI into its components
73let aturi = ATURI::from_str("at://did:plc:abc123/app.bsky.feed.post/3k2k4j5h6g")?;
74
75// Access the parsed components
76println!("Authority: {}", aturi.authority); // "did:plc:abc123"
77println!("Collection: {}", aturi.collection); // "app.bsky.feed.post"
78println!("Record Key: {}", aturi.record_key); // "3k2k4j5h6g"
79
80// The Display trait formats back to a valid AT-URI
81println!("Full URI: {}", aturi); // "at://did:plc:abc123/app.bsky.feed.post/3k2k4j5h6g"
82```
83
84### DateTime Utilities
85
86```rust
87use chrono::{DateTime, Utc};
88use serde::{Deserialize, Serialize};
89
90// Use the datetime module for consistent RFC 3339 formatting
91#[derive(Serialize, Deserialize)]
92struct Record {
93 #[serde(with = "atproto_record::datetime::format")]
94 created_at: DateTime<Utc>,
95
96 #[serde(with = "atproto_record::datetime::optional_format")]
97 updated_at: Option<DateTime<Utc>>,
98}
99```
100
101## Command Line Usage
102
103The CLI tool requires the `clap` feature:
104
105```bash
106# Build with CLI support
107cargo build --features clap --bins
108
109# Generate CID from JSON file
110cat record.json | cargo run --features clap --bin atproto-record-cid
111
112# Generate CID from inline JSON
113echo '{"$type":"app.bsky.feed.post","text":"Hello!"}' | cargo run --features clap --bin atproto-record-cid
114
115# Example with a complete AT Protocol record
116cat <<EOF | cargo run --features clap --bin atproto-record-cid
117{
118 "$type": "app.bsky.feed.post",
119 "text": "Hello AT Protocol!",
120 "createdAt": "2024-01-01T00:00:00.000Z"
121}
122EOF
123```
124
125The tool outputs the CID in base32 format:
126```
127bafyreibjzlvhtyxnhbvvzl3gj4qmg2ufl2jbhh5qr3gvvxlm7ksf3qwxqq
128```
129
130## License
131
132MIT License