tangled
alpha
login
or
join now
smokesignal.events
/
atproto-identity-rs
22
fork
atom
A library for ATProtocol identities.
22
fork
atom
overview
issues
2
pulls
pipelines
migration notice
Nick Gerakines
4 days ago
1cd8cc2f
9964314c
+2
-350
1 changed file
expand all
collapse all
unified
split
README.md
+2
-350
README.md
···
1
1
-
# AT Protocol Identity Rust Components
2
2
-
3
3
-
A comprehensive collection of Rust components for creating AT Protocol applications. This workspace provides essential building blocks for content-addressed data, identity management, repository operations, record signing, OAuth 2.0 authentication flows, HTTP client operations, XRPC services, and real-time event streaming.
4
4
-
5
5
-
**Origin**: Parts of this project were extracted from the open-source [smokesignal.events](https://tangled.sh/@smokesignal.events/smokesignal) project, an AT Protocol event and RSVP management application. This library is released under the MIT license to enable broader AT Protocol ecosystem development.
6
6
-
7
7
-
## Components
8
8
-
9
9
-
This workspace contains 15 specialized crates that work together to provide complete AT Protocol application development capabilities:
10
10
-
11
11
-
### Data Foundations
12
12
-
13
13
-
- **[`atproto-dasl`](crates/atproto-dasl/)** - DASL (Data-Addressed Structures & Links) framework implementing CID computation, DRISL (deterministic DAG-CBOR encoding), CAR v1 archives, block storage backends, RASL retrieval, BDASL large file hashing, and Web Tiles. *Includes 1 CLI tool.*
14
14
-
15
15
-
### Identity & Cryptography
16
16
-
17
17
-
- **[`atproto-identity`](crates/atproto-identity/)** - Core identity management with multi-method DID resolution (plc, web, key), DNS/HTTP handle resolution, PLC directory operations, and P-256/P-384/K-256 cryptographic operations. *Includes 6 CLI tools.*
18
18
-
- **[`atproto-attestation`](crates/atproto-attestation/)** - CID-first attestation utilities for creating and verifying cryptographic signatures on AT Protocol records, supporting both inline and remote attestation workflows. *Includes 2 CLI tools.*
19
19
-
- **[`atproto-record`](crates/atproto-record/)** - Record utilities including TID generation, AT-URI parsing, datetime formatting, and CID generation using IPLD DAG-CBOR serialization. *Includes 1 CLI tool.*
20
20
-
- **[`atproto-lexicon`](crates/atproto-lexicon/)** - Lexicon schema resolution and validation for AT Protocol, supporting recursive resolution, NSID validation, and DNS-based lexicon discovery. *Includes 1 CLI tool.*
21
21
-
22
22
-
### Repository
23
23
-
24
24
-
- **[`atproto-repo`](crates/atproto-repo/)** - AT Protocol repository handling with Merkle Search Tree (MST) encoding/decoding, commit structures, tree diffing for sync, and configurable verification. Builds on `atproto-dasl` for CAR and storage. *Includes 2 CLI tools.*
25
25
-
26
26
-
### Authentication & Authorization
27
27
-
28
28
-
- **[`atproto-oauth`](crates/atproto-oauth/)** - Complete OAuth 2.0 implementation with AT Protocol security extensions including DPoP (RFC 9449), PKCE (RFC 7636), JWT operations, and secure storage abstractions. *Includes 1 CLI tool.*
29
29
-
- **[`atproto-oauth-aip`](crates/atproto-oauth-aip/)** - OAuth AIP (Identity Provider) implementation providing complete authorization code flow with PAR, token exchange, and AT Protocol session management.
30
30
-
- **[`atproto-oauth-axum`](crates/atproto-oauth-axum/)** - Production-ready Axum web handlers for OAuth endpoints including authorization callbacks, JWKS endpoints, and client metadata. *Includes 1 CLI tool.*
31
31
-
32
32
-
### Client & Service Development
33
33
-
34
34
-
- **[`atproto-client`](crates/atproto-client/)** - HTTP client library supporting multiple authentication methods (DPoP, Bearer tokens, sessions) with native XRPC protocol operations and repository management. *Includes 4 CLI tools.*
35
35
-
- **[`atproto-xrpcs`](crates/atproto-xrpcs/)** - XRPC service framework providing JWT authorization extractors, DID resolution integration, and Axum middleware for building AT Protocol services.
36
36
-
- **[`atproto-xrpcs-helloworld`](crates/atproto-xrpcs-helloworld/)** - Complete example XRPC service demonstrating DID:web identity, service document generation, and JWT authentication patterns. *Includes 1 service binary.*
37
37
-
38
38
-
### Real-time Event Processing
39
39
-
40
40
-
- **[`atproto-jetstream`](crates/atproto-jetstream/)** - WebSocket consumer for AT Protocol Jetstream events with Zstandard compression, automatic reconnection, and configurable event filtering. *Includes 1 CLI tool.*
41
41
-
- **[`atproto-tap`](crates/atproto-tap/)** - TAP (Trusted Attestation Protocol) service consumer for filtered, verified AT Protocol repository events with MST integrity checks, automatic backfill, and acknowledgment-based delivery. *Includes 2 CLI tools.*
42
42
-
43
43
-
### Utilities
44
44
-
45
45
-
- **[`atproto-extras`](crates/atproto-extras/)** - Facet parsing and rich text utilities for AT Protocol, extracting mentions, URLs, and hashtags from plain text with correct UTF-8 byte offset calculation. *Includes 1 CLI tool.*
46
46
-
47
47
-
## Quick Start
48
48
-
49
49
-
Add the crates to your `Cargo.toml`:
50
50
-
51
51
-
```toml
52
52
-
[dependencies]
53
53
-
atproto-dasl = "0.13.0"
54
54
-
atproto-identity = "0.13.0"
55
55
-
atproto-attestation = "0.13.0"
56
56
-
atproto-record = "0.13.0"
57
57
-
atproto-repo = "0.13.0"
58
58
-
atproto-lexicon = "0.13.0"
59
59
-
atproto-oauth = "0.13.0"
60
60
-
atproto-oauth-aip = "0.13.0"
61
61
-
atproto-client = "0.13.0"
62
62
-
atproto-extras = "0.13.0"
63
63
-
atproto-tap = "0.13.0"
64
64
-
# Add others as needed
65
65
-
```
66
66
-
67
67
-
### Basic Identity Resolution
68
68
-
69
69
-
```rust
70
70
-
use atproto_identity::resolve::{resolve_subject, create_resolver};
71
71
-
72
72
-
#[tokio::main]
73
73
-
async fn main() -> anyhow::Result<()> {
74
74
-
let http_client = reqwest::Client::new();
75
75
-
let dns_resolver = create_resolver(&[]);
76
76
-
77
77
-
let did = resolve_subject(&http_client, &dns_resolver, "alice.bsky.social").await?;
78
78
-
println!("Resolved DID: {}", did);
79
79
-
80
80
-
Ok(())
81
81
-
}
82
82
-
```
83
83
-
84
84
-
### Lexicon Resolution
85
85
-
86
86
-
```rust
87
87
-
use atproto_lexicon::resolve::{DefaultLexiconResolver, LexiconResolver};
88
88
-
use atproto_identity::resolve::HickoryDnsResolver;
89
89
-
90
90
-
#[tokio::main]
91
91
-
async fn main() -> anyhow::Result<()> {
92
92
-
let http_client = reqwest::Client::new();
93
93
-
let dns_resolver = HickoryDnsResolver::create_resolver(&[]);
94
94
-
let resolver = DefaultLexiconResolver::new(http_client, dns_resolver);
95
95
-
96
96
-
// Resolve a lexicon schema
97
97
-
let lexicon = resolver.resolve("app.bsky.feed.post").await?;
98
98
-
println!("Lexicon schema: {}", serde_json::to_string_pretty(&lexicon)?);
99
99
-
100
100
-
Ok(())
101
101
-
}
102
102
-
```
103
103
-
104
104
-
### Record Signing
105
105
-
106
106
-
```rust
107
107
-
use atproto_attestation::{create_inline_attestation, AnyInput};
108
108
-
use atproto_identity::key::{generate_key, KeyType};
109
109
-
use serde_json::json;
110
110
-
111
111
-
fn main() -> anyhow::Result<()> {
112
112
-
let key = generate_key(KeyType::P256Private)?;
113
113
-
114
114
-
let record = json!({
115
115
-
"$type": "app.bsky.feed.post",
116
116
-
"text": "Hello AT Protocol!",
117
117
-
"createdAt": "2024-01-01T00:00:00.000Z"
118
118
-
});
119
119
-
120
120
-
let metadata = json!({
121
121
-
"$type": "com.example.inlineSignature",
122
122
-
"key": "did:key:...",
123
123
-
"issuer": "did:plc:issuer123",
124
124
-
"issuedAt": "2024-01-01T00:00:00.000Z"
125
125
-
});
126
126
-
127
127
-
let signed_record = create_inline_attestation(
128
128
-
AnyInput::Serialize(record),
129
129
-
AnyInput::Serialize(metadata),
130
130
-
"did:plc:repo123",
131
131
-
&key
132
132
-
)?;
133
133
-
134
134
-
println!("Signed record: {}", serde_json::to_string_pretty(&signed_record)?);
135
135
-
Ok(())
136
136
-
}
137
137
-
```
138
138
-
139
139
-
### XRPC Service
140
140
-
141
141
-
```rust
142
142
-
use atproto_xrpcs::authorization::Authorization;
143
143
-
use axum::{Json, Router, extract::Query, routing::get};
144
144
-
use serde::Deserialize;
145
145
-
use serde_json::json;
146
146
-
147
147
-
#[derive(Deserialize)]
148
148
-
struct HelloParams {
149
149
-
subject: Option<String>,
150
150
-
}
151
151
-
152
152
-
async fn handle_hello(
153
153
-
params: Query<HelloParams>,
154
154
-
authorization: Option<Authorization>,
155
155
-
) -> Json<serde_json::Value> {
156
156
-
let subject = params.subject.as_deref().unwrap_or("World");
157
157
-
158
158
-
let message = if let Some(auth) = authorization {
159
159
-
format!("Hello, authenticated {}! (caller: {})", subject, auth.subject())
160
160
-
} else {
161
161
-
format!("Hello, {}!", subject)
162
162
-
};
163
163
-
164
164
-
Json(json!({ "message": message }))
165
165
-
}
166
166
-
167
167
-
#[tokio::main]
168
168
-
async fn main() -> anyhow::Result<()> {
169
169
-
let app = Router::new()
170
170
-
.route("/xrpc/com.example.hello", get(handle_hello))
171
171
-
.with_state(your_web_context);
172
172
-
173
173
-
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
174
174
-
axum::serve(listener, app).await?;
175
175
-
176
176
-
Ok(())
177
177
-
}
178
178
-
```
179
179
-
180
180
-
### OAuth Client Flow
181
181
-
182
182
-
```rust
183
183
-
use atproto_oauth_aip::workflow::{oauth_init, oauth_complete, session_exchange, OAuthClient};
184
184
-
use atproto_oauth::workflow::OAuthRequestState;
185
185
-
186
186
-
#[tokio::main]
187
187
-
async fn main() -> anyhow::Result<()> {
188
188
-
let http_client = reqwest::Client::new();
189
189
-
190
190
-
let oauth_client = OAuthClient {
191
191
-
redirect_uri: "https://your-app.com/callback".to_string(),
192
192
-
client_id: "your-client-id".to_string(),
193
193
-
client_secret: "your-client-secret".to_string(),
194
194
-
};
195
195
-
196
196
-
let oauth_request_state = OAuthRequestState {
197
197
-
state: "random-state".to_string(),
198
198
-
nonce: "random-nonce".to_string(),
199
199
-
code_challenge: "code-challenge".to_string(),
200
200
-
scope: "atproto transition:generic".to_string(),
201
201
-
};
202
202
-
203
203
-
// 1. Start OAuth flow with Pushed Authorization Request
204
204
-
let par_response = oauth_init(
205
205
-
&http_client,
206
206
-
&oauth_client,
207
207
-
Some("alice.bsky.social"),
208
208
-
"https://auth-server.example.com/par",
209
209
-
&oauth_request_state,
210
210
-
).await?;
211
211
-
212
212
-
println!("PAR request URI: {}", par_response.request_uri);
213
213
-
214
214
-
// 2. After user authorizes and returns with a code, exchange it for tokens
215
215
-
let token_response = oauth_complete(
216
216
-
&http_client,
217
217
-
&oauth_client,
218
218
-
"https://auth-server.example.com/token",
219
219
-
"received-auth-code",
220
220
-
&oauth_request, // OAuthRequest from your stored state
221
221
-
).await?;
222
222
-
223
223
-
// 3. Exchange token for AT Protocol session
224
224
-
let session = session_exchange(
225
225
-
&http_client,
226
226
-
"https://pds.example.com",
227
227
-
&token_response.access_token,
228
228
-
).await?;
229
229
-
230
230
-
println!("Authenticated as: {} ({})", session.handle, session.did);
231
231
-
232
232
-
Ok(())
233
233
-
}
234
234
-
```
235
235
-
236
236
-
## Command Line Tools
237
237
-
238
238
-
The workspace includes 23 command-line tools across 11 crates, providing ready-to-use utilities for AT Protocol development and testing. Most CLI tools require the `clap` feature:
239
239
-
240
240
-
```bash
241
241
-
# Build with CLI support
242
242
-
cargo build --features clap --bins
243
243
-
244
244
-
# DASL operations (atproto-dasl crate)
245
245
-
cargo run --package atproto-dasl --features clap --bin atproto-dasl -- --help
246
246
-
247
247
-
# Identity operations (atproto-identity crate)
248
248
-
cargo run --features clap,hickory-dns --bin atproto-identity-resolve -- alice.bsky.social
249
249
-
cargo run --features clap --bin atproto-identity-key -- generate p256
250
250
-
cargo run --features clap --bin atproto-identity-sign -- did:key:... data.json
251
251
-
cargo run --features clap --bin atproto-identity-validate -- did:key:... data.json signature
252
252
-
cargo run --features clap,hickory-dns --bin atproto-identity-plc-audit -- did:plc:...
253
253
-
cargo run --features clap,hickory-dns --bin atproto-identity-plc-fork-viz -- did:plc:...
254
254
-
255
255
-
# Attestation operations (atproto-attestation crate)
256
256
-
cargo run --package atproto-attestation --features clap,tokio --bin atproto-attestation-sign -- inline record.json did:key:... metadata.json
257
257
-
cargo run --package atproto-attestation --features clap,tokio --bin atproto-attestation-verify -- signed_record.json
258
258
-
259
259
-
# Record operations (atproto-record crate)
260
260
-
cat record.json | cargo run --features clap --bin atproto-record-cid
261
261
-
262
262
-
# Repository operations (atproto-repo crate)
263
263
-
cargo run --package atproto-repo --features clap --bin atproto-repo-car -- ls repo.car
264
264
-
cargo run --package atproto-repo --features clap --bin atproto-repo-mst -- ls repo.car
265
265
-
266
266
-
# Lexicon operations (atproto-lexicon crate)
267
267
-
cargo run --features clap,hickory-dns --bin atproto-lexicon-resolve -- app.bsky.feed.post
268
268
-
269
269
-
# Client operations (atproto-client crate)
270
270
-
cargo run --features clap --bin atproto-client-auth -- login alice.bsky.social password123
271
271
-
cargo run --features clap --bin atproto-client-app-password -- alice.bsky.social access_token /xrpc/com.atproto.repo.listRecords
272
272
-
cargo run --features clap --bin atproto-client-dpop -- alice.bsky.social did:key:... access_token /xrpc/com.atproto.repo.listRecords
273
273
-
cargo run --features clap --bin atproto-client-put-record -- --help
274
274
-
275
275
-
# OAuth operations (atproto-oauth crate)
276
276
-
cargo run --package atproto-oauth --features clap --bin atproto-oauth-service-token -- --help
277
277
-
278
278
-
# OAuth operations (atproto-oauth-axum crate)
279
279
-
cargo run --package atproto-oauth-axum --features clap --bin atproto-oauth-tool -- login did:key:... alice.bsky.social
280
280
-
281
281
-
# XRPC service (atproto-xrpcs-helloworld crate)
282
282
-
cargo run --bin atproto-xrpcs-helloworld
283
283
-
284
284
-
# Event streaming (atproto-jetstream crate)
285
285
-
cargo run --features clap --bin atproto-jetstream-consumer -- jetstream1.us-east.bsky.network dictionary.zstd
286
286
-
287
287
-
# TAP service consumer (atproto-tap crate)
288
288
-
cargo run --package atproto-tap --features clap --bin atproto-tap-client -- --help
289
289
-
cargo run --package atproto-tap --features clap --bin atproto-tap-extras -- --help
290
290
-
291
291
-
# Rich text utilities (atproto-extras crate)
292
292
-
cargo run --package atproto-extras --features clap,cli,hickory-dns --bin atproto-extras-parse-facets -- "Hello @alice.bsky.social"
293
293
-
```
294
294
-
295
295
-
## Development
296
296
-
297
297
-
```bash
298
298
-
# Build all crates
299
299
-
cargo build
300
300
-
301
301
-
# Run all tests
302
302
-
cargo test
303
303
-
304
304
-
# Format and lint
305
305
-
cargo fmt && cargo clippy
306
306
-
307
307
-
# Generate documentation
308
308
-
cargo doc --workspace --open
309
309
-
```
310
310
-
311
311
-
## License
312
312
-
313
313
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
314
314
-
315
315
-
## Architecture
316
316
-
317
317
-
These components are designed to work together as building blocks for AT Protocol applications:
318
318
-
319
319
-
- **Data Foundation Layer**: `atproto-dasl` provides CID computation, deterministic DAG-CBOR encoding, CAR v1 archives, and pluggable block storage
320
320
-
- **Identity Layer**: `atproto-identity` provides the foundation for DID resolution and cryptographic operations
321
321
-
- **Repository Layer**: `atproto-repo` provides Merkle Search Tree operations, commit structures, and repository handling
322
322
-
- **Data Layer**: `atproto-record` and `atproto-attestation` handle record operations, CID generation, and cryptographic attestations
323
323
-
- **Schema Layer**: `atproto-lexicon` provides lexicon resolution and validation for AT Protocol schemas
324
324
-
- **Authentication Layer**: `atproto-oauth*` crates handle complete OAuth 2.0 flows with AT Protocol security extensions
325
325
-
- **Application Layer**: `atproto-client` and `atproto-xrpcs*` enable client applications and service development
326
326
-
- **Event Layer**: `atproto-jetstream` and `atproto-tap` provide real-time event processing capabilities
327
327
-
- **Utilities Layer**: `atproto-extras` provides rich text facet parsing for AT Protocol applications
328
328
-
329
329
-
## Use Cases
330
330
-
331
331
-
This workspace enables development of:
332
332
-
333
333
-
- **AT Protocol Identity Providers (AIPs)** - Complete OAuth servers with DID-based authentication
334
334
-
- **Personal Data Servers (PDS)** - XRPC services with JWT authorization and repository management
335
335
-
- **AT Protocol Clients** - Applications that authenticate and interact with AT Protocol services
336
336
-
- **Event Processing Systems** - Real-time processors for AT Protocol repository events via Jetstream or TAP
337
337
-
- **Repository Tools** - CAR file inspection, MST analysis, and repository verification utilities
338
338
-
- **Development Tools** - CLI utilities for testing, debugging, and managing AT Protocol identities
339
339
-
340
340
-
## Contributing
341
341
-
342
342
-
Contributions are welcome! This project follows standard Rust development practices:
1
1
+
# atproto-crates
343
2
344
344
-
1. Fork this repository
345
345
-
2. Create a feature branch
346
346
-
3. Run tests: `cargo test`
347
347
-
4. Run linting: `cargo fmt && cargo clippy`
348
348
-
5. Submit a pull request
3
3
+
This project has a new home at: https://tangled.org/ngerakines.me/atproto-crates
349
4
350
350
-
## Acknowledgments
351
351
-
352
352
-
Parts of this project were extracted from the [smokesignal.events](https://tangled.sh/@smokesignal.events/smokesignal) project, an open-source AT Protocol event and RSVP management application. This extraction enables broader community use and contribution to AT Protocol tooling in Rust.