+38
-3
Cargo.lock
+38
-3
Cargo.lock
···
1539
"bon",
1540
"bytes",
1541
"clap",
1542
-
"hickory-resolver",
1543
"http",
1544
"jacquard-api",
1545
"jacquard-common",
1546
"jacquard-derive",
1547
"jacquard-oauth",
1548
"jose-jwk",
1549
"miette",
···
1588
"cid",
1589
"ed25519-dalek",
1590
"enum_dispatch",
1591
-
"hickory-resolver",
1592
"http",
1593
"ipld-core",
1594
"k256",
···
1610
"smol_str",
1611
"thiserror 2.0.17",
1612
"tokio",
1613
"url",
1614
]
1615
···
1631
]
1632
1633
[[package]]
1634
name = "jacquard-lexicon"
1635
version = "0.2.0"
1636
dependencies = [
···
1657
dependencies = [
1658
"async-trait",
1659
"base64 0.22.1",
1660
-
"bon",
1661
"chrono",
1662
"dashmap",
1663
"elliptic-curve",
1664
"http",
1665
"jacquard-common",
1666
"jose-jwa",
1667
"jose-jwk",
1668
"miette",
···
1678
"smol_str",
1679
"thiserror 2.0.17",
1680
"tokio",
1681
"url",
1682
"uuid",
1683
]
···
3344
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
3345
dependencies = [
3346
"once_cell",
3347
]
3348
3349
[[package]]
···
1539
"bon",
1540
"bytes",
1541
"clap",
1542
"http",
1543
"jacquard-api",
1544
"jacquard-common",
1545
"jacquard-derive",
1546
+
"jacquard-identity",
1547
"jacquard-oauth",
1548
"jose-jwk",
1549
"miette",
···
1588
"cid",
1589
"ed25519-dalek",
1590
"enum_dispatch",
1591
"http",
1592
"ipld-core",
1593
"k256",
···
1609
"smol_str",
1610
"thiserror 2.0.17",
1611
"tokio",
1612
+
"trait-variant",
1613
"url",
1614
]
1615
···
1631
]
1632
1633
[[package]]
1634
+
name = "jacquard-identity"
1635
+
version = "0.2.0"
1636
+
dependencies = [
1637
+
"async-trait",
1638
+
"bon",
1639
+
"bytes",
1640
+
"hickory-resolver",
1641
+
"http",
1642
+
"jacquard-api",
1643
+
"jacquard-common",
1644
+
"miette",
1645
+
"percent-encoding",
1646
+
"reqwest",
1647
+
"serde",
1648
+
"serde_html_form",
1649
+
"serde_json",
1650
+
"thiserror 2.0.17",
1651
+
"tokio",
1652
+
"url",
1653
+
"urlencoding",
1654
+
]
1655
+
1656
+
[[package]]
1657
name = "jacquard-lexicon"
1658
version = "0.2.0"
1659
dependencies = [
···
1680
dependencies = [
1681
"async-trait",
1682
"base64 0.22.1",
1683
"chrono",
1684
"dashmap",
1685
"elliptic-curve",
1686
"http",
1687
"jacquard-common",
1688
+
"jacquard-identity",
1689
"jose-jwa",
1690
"jose-jwk",
1691
"miette",
···
1701
"smol_str",
1702
"thiserror 2.0.17",
1703
"tokio",
1704
+
"trait-variant",
1705
"url",
1706
"uuid",
1707
]
···
3368
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
3369
dependencies = [
3370
"once_cell",
3371
+
]
3372
+
3373
+
[[package]]
3374
+
name = "trait-variant"
3375
+
version = "0.1.2"
3376
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3377
+
checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7"
3378
+
dependencies = [
3379
+
"proc-macro2",
3380
+
"quote",
3381
+
"syn 2.0.106",
3382
]
3383
3384
[[package]]
+6
Cargo.toml
+6
Cargo.toml
+1
-2
crates/jacquard-common/Cargo.toml
+1
-2
crates/jacquard-common/Cargo.toml
···
39
async-trait = "0.1"
40
tokio = { version = "1", features = ["sync"] }
41
reqwest = { workspace = true, optional = true, features = ["charset", "http2", "json", "system-proxy", "gzip", "rustls-tls"] }
42
-
hickory-resolver = { version = "0.24", default-features = false, features = ["system-config", "tokio-runtime"], optional = true }
43
serde_ipld_dagcbor.workspace = true
44
45
[features]
46
default = []
47
-
dns = ["dep:hickory-resolver"]
48
crypto = []
49
crypto-ed25519 = ["crypto", "dep:ed25519-dalek"]
50
crypto-k256 = ["crypto", "dep:k256"]
···
39
async-trait = "0.1"
40
tokio = { version = "1", features = ["sync"] }
41
reqwest = { workspace = true, optional = true, features = ["charset", "http2", "json", "system-proxy", "gzip", "rustls-tls"] }
42
serde_ipld_dagcbor.workspace = true
43
+
trait-variant.workspace = true
44
45
[features]
46
default = []
47
crypto = []
48
crypto-ed25519 = ["crypto", "dep:ed25519-dalek"]
49
crypto-k256 = ["crypto", "dep:k256"]
+2
-2
crates/jacquard-common/src/cowstr.rs
+2
-2
crates/jacquard-common/src/cowstr.rs
+12
-12
crates/jacquard-common/src/ident_resolver.rs
crates/jacquard-identity/src/resolver.rs
+12
-12
crates/jacquard-common/src/ident_resolver.rs
crates/jacquard-identity/src/resolver.rs
···
12
use std::collections::BTreeMap;
13
use std::str::FromStr;
14
15
-
use crate::error::TransportError;
16
-
use crate::types::did_doc::Service;
17
-
use crate::types::ident::AtIdentifier;
18
-
use crate::types::string::AtprotoStr;
19
-
use crate::types::uri::Uri;
20
-
use crate::types::value::Data;
21
-
use crate::{CowStr, IntoStatic};
22
use bon::Builder;
23
use bytes::Bytes;
24
use http::StatusCode;
25
use miette::Diagnostic;
26
use thiserror::Error;
27
use url::Url;
28
29
-
use crate::types::did_doc::DidDocument;
30
-
use crate::types::string::{Did, Handle};
31
-
use crate::types::value::AtDataError;
32
/// Errors that can occur during identity resolution.
33
///
34
/// Note: when validating a fetched DID document against a requested DID, a
···
114
/// mismatch). Use `into_owned()` to parse into an owned document.
115
#[derive(Clone)]
116
pub struct DidDocResponse {
117
pub buffer: Bytes,
118
pub status: StatusCode,
119
/// Optional DID we intended to resolve; used for validation helpers
120
pub requested: Option<Did<'static>>,
···
205
#[serde(borrow)]
206
pub handle: Handle<'a>,
207
#[serde(borrow)]
208
-
pub pds: crate::CowStr<'a>,
209
#[serde(borrow, rename = "signingKey", alias = "signing_key")]
210
-
pub signing_key: crate::CowStr<'a>,
211
}
212
213
/// Handle → DID fallback step.
···
12
use std::collections::BTreeMap;
13
use std::str::FromStr;
14
15
use bon::Builder;
16
use bytes::Bytes;
17
use http::StatusCode;
18
+
use jacquard_common::error::TransportError;
19
+
use jacquard_common::types::did::Did;
20
+
use jacquard_common::types::did_doc::{DidDocument, Service};
21
+
use jacquard_common::types::ident::AtIdentifier;
22
+
use jacquard_common::types::string::{AtprotoStr, Handle};
23
+
use jacquard_common::types::uri::Uri;
24
+
use jacquard_common::types::value::{AtDataError, Data};
25
+
use jacquard_common::{CowStr, IntoStatic};
26
use miette::Diagnostic;
27
use thiserror::Error;
28
use url::Url;
29
30
/// Errors that can occur during identity resolution.
31
///
32
/// Note: when validating a fetched DID document against a requested DID, a
···
112
/// mismatch). Use `into_owned()` to parse into an owned document.
113
#[derive(Clone)]
114
pub struct DidDocResponse {
115
+
#[allow(missing_docs)]
116
pub buffer: Bytes,
117
+
#[allow(missing_docs)]
118
pub status: StatusCode,
119
/// Optional DID we intended to resolve; used for validation helpers
120
pub requested: Option<Did<'static>>,
···
205
#[serde(borrow)]
206
pub handle: Handle<'a>,
207
#[serde(borrow)]
208
+
pub pds: CowStr<'a>,
209
#[serde(borrow, rename = "signingKey", alias = "signing_key")]
210
+
pub signing_key: CowStr<'a>,
211
}
212
213
/// Handle → DID fallback step.
-1
crates/jacquard-common/src/lib.rs
-1
crates/jacquard-common/src/lib.rs
+35
crates/jacquard-identity/Cargo.toml
+35
crates/jacquard-identity/Cargo.toml
···
···
1
+
[package]
2
+
name = "jacquard-identity"
3
+
edition.workspace = true
4
+
version.workspace = true
5
+
authors.workspace = true
6
+
repository.workspace = true
7
+
keywords.workspace = true
8
+
categories.workspace = true
9
+
readme.workspace = true
10
+
exclude.workspace = true
11
+
homepage.workspace = true
12
+
license.workspace = true
13
+
description.workspace = true
14
+
15
+
[features]
16
+
dns = ["dep:hickory-resolver"]
17
+
18
+
[dependencies]
19
+
async-trait = "0.1.89"
20
+
bon.workspace = true
21
+
bytes.workspace = true
22
+
jacquard-common = { version = "0.2", path = "../jacquard-common" }
23
+
percent-encoding = "2.3.2"
24
+
reqwest.workspace = true
25
+
url.workspace = true
26
+
tokio = { version = "1", features = ["macros", "rt-multi-thread", "fs"] }
27
+
hickory-resolver = { optional = true, version = "0.24", default-features = false, features = ["system-config", "tokio-runtime"]}
28
+
serde.workspace = true
29
+
serde_json.workspace = true
30
+
thiserror.workspace = true
31
+
miette.workspace = true
32
+
http.workspace = true
33
+
jacquard-api = { version = "0.2.0", path = "../jacquard-api" }
34
+
serde_html_form.workspace = true
35
+
urlencoding = "2.1.3"
+3
-1
crates/jacquard-oauth/Cargo.toml
+3
-1
crates/jacquard-oauth/Cargo.toml
+1
-1
crates/jacquard-oauth/src/atproto.rs
+1
-1
crates/jacquard-oauth/src/atproto.rs
-13
crates/jacquard-oauth/src/dpop.rs
-13
crates/jacquard-oauth/src/dpop.rs
···
63
{
64
DpopCall::client(self, data_source)
65
}
66
-
67
-
async fn wrap_with_dpop<'r, D>(
68
-
&'r self,
69
-
is_to_auth_server: bool,
70
-
data_source: &'r mut D,
71
-
request: Request<Vec<u8>>,
72
-
) -> Result<Response<Vec<u8>>>
73
-
where
74
-
Self: Sized,
75
-
D: DpopDataSource,
76
-
{
77
-
wrap_request_with_dpop(self, data_source, is_to_auth_server, request).await
78
-
}
79
}
80
81
pub struct DpopCall<'r, C: HttpClient, D: DpopDataSource> {
+13
-17
crates/jacquard-oauth/src/request.rs
+13
-17
crates/jacquard-oauth/src/request.rs
···
1
-
use chrono::{DateTime, FixedOffset, TimeDelta, Utc};
2
use http::{Method, Request, StatusCode};
3
use jacquard_common::{
4
CowStr, IntoStatic,
5
cowstr::ToCowStr,
6
http_client::HttpClient,
7
-
ident_resolver::{IdentityError, IdentityResolver},
8
session::SessionStoreError,
9
types::{
10
did::Did,
11
string::{AtStrError, Datetime},
12
},
13
};
14
-
use jose_jwk::Key;
15
-
use serde::{Serialize, de::DeserializeOwned};
16
use serde_json::Value;
17
use smol_str::ToSmolStr;
18
-
use std::sync::Arc;
19
use thiserror::Error;
20
-
use url::Url;
21
22
use crate::{
23
FALLBACK_ALG,
24
-
atproto::{AtprotoClientMetadata, atproto_client_metadata},
25
-
dpop::{DpopClient, DpopExt},
26
jose::jwt::{RegisteredClaims, RegisteredClaimsAud},
27
keyset::Keyset,
28
resolver::OAuthResolver,
···
424
}
425
}
426
427
fn endpoint_for_req<'a, 'r>(
428
server_metadata: &'r OAuthAuthorizationServerMetadata<'a>,
429
request: &'r OAuthRequest,
···
438
}
439
}
440
441
-
fn build_oauth_req_body<'a, S>(
442
-
client_assertions: ClientAssertions<'a>,
443
-
parameters: S,
444
-
) -> Result<String>
445
where
446
S: Serialize,
447
{
···
454
}
455
456
#[derive(Debug, Clone, Default)]
457
-
pub struct ClientAssertions<'a> {
458
client_id: CowStr<'a>,
459
assertion_type: Option<CowStr<'a>>, // either none or `CLIENT_ASSERTION_TYPE_JWT_BEARER`
460
assertion: Option<CowStr<'a>>,
461
}
462
463
-
impl<'s> ClientAssertions<'s> {
464
pub fn new_id(client_id: CowStr<'s>) -> Self {
465
Self {
466
client_id,
···
474
keyset: Option<&Keyset>,
475
server_metadata: &OAuthAuthorizationServerMetadata<'a>,
476
client_metadata: &OAuthClientMetadata<'a>,
477
-
) -> Result<ClientAssertions<'a>> {
478
let method_supported = server_metadata
479
.token_endpoint_auth_methods_supported
480
.as_ref();
···
494
.unwrap_or(vec![FALLBACK_ALG.into()]);
495
algs.sort_by(compare_algos);
496
let iat = Utc::now().timestamp();
497
-
return Ok(ClientAssertions {
498
client_id: client_id.clone(),
499
assertion_type: Some(CowStr::new_static(CLIENT_ASSERTION_TYPE_JWT_BEARER)),
500
assertion: Some(
···
526
.as_ref()
527
.is_some_and(|v| v.contains(&CowStr::new_static("none"))) =>
528
{
529
-
return Ok(ClientAssertions::new_id(client_id));
530
}
531
_ => {}
532
}
···
1
+
use chrono::{TimeDelta, Utc};
2
use http::{Method, Request, StatusCode};
3
use jacquard_common::{
4
CowStr, IntoStatic,
5
cowstr::ToCowStr,
6
http_client::HttpClient,
7
session::SessionStoreError,
8
types::{
9
did::Did,
10
string::{AtStrError, Datetime},
11
},
12
};
13
+
use jacquard_identity::resolver::IdentityError;
14
+
use serde::Serialize;
15
use serde_json::Value;
16
use smol_str::ToSmolStr;
17
use thiserror::Error;
18
19
use crate::{
20
FALLBACK_ALG,
21
+
atproto::atproto_client_metadata,
22
+
dpop::DpopExt,
23
jose::jwt::{RegisteredClaims, RegisteredClaimsAud},
24
keyset::Keyset,
25
resolver::OAuthResolver,
···
421
}
422
}
423
424
+
#[inline]
425
fn endpoint_for_req<'a, 'r>(
426
server_metadata: &'r OAuthAuthorizationServerMetadata<'a>,
427
request: &'r OAuthRequest,
···
436
}
437
}
438
439
+
#[inline]
440
+
fn build_oauth_req_body<'a, S>(client_assertions: ClientAuth<'a>, parameters: S) -> Result<String>
441
where
442
S: Serialize,
443
{
···
450
}
451
452
#[derive(Debug, Clone, Default)]
453
+
pub struct ClientAuth<'a> {
454
client_id: CowStr<'a>,
455
assertion_type: Option<CowStr<'a>>, // either none or `CLIENT_ASSERTION_TYPE_JWT_BEARER`
456
assertion: Option<CowStr<'a>>,
457
}
458
459
+
impl<'s> ClientAuth<'s> {
460
pub fn new_id(client_id: CowStr<'s>) -> Self {
461
Self {
462
client_id,
···
470
keyset: Option<&Keyset>,
471
server_metadata: &OAuthAuthorizationServerMetadata<'a>,
472
client_metadata: &OAuthClientMetadata<'a>,
473
+
) -> Result<ClientAuth<'a>> {
474
let method_supported = server_metadata
475
.token_endpoint_auth_methods_supported
476
.as_ref();
···
490
.unwrap_or(vec![FALLBACK_ALG.into()]);
491
algs.sort_by(compare_algos);
492
let iat = Utc::now().timestamp();
493
+
return Ok(ClientAuth {
494
client_id: client_id.clone(),
495
assertion_type: Some(CowStr::new_static(CLIENT_ASSERTION_TYPE_JWT_BEARER)),
496
assertion: Some(
···
522
.as_ref()
523
.is_some_and(|v| v.contains(&CowStr::new_static("none"))) =>
524
{
525
+
return Ok(ClientAuth::new_id(client_id));
526
}
527
_ => {}
528
}
+1
-5
crates/jacquard-oauth/src/resolver.rs
+1
-5
crates/jacquard-oauth/src/resolver.rs
···
1
use crate::types::{OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata};
2
use http::{Request, StatusCode};
3
use jacquard_common::IntoStatic;
4
-
use jacquard_common::ident_resolver::{IdentityError, IdentityResolver};
5
use jacquard_common::types::did_doc::DidDocument;
6
use jacquard_common::types::ident::AtIdentifier;
7
use jacquard_common::{http_client::HttpClient, types::did::Did};
8
-
use sha2::digest::const_oid::Arc;
9
use url::Url;
10
11
#[derive(thiserror::Error, Debug, miette::Diagnostic)]
···
160
Ok(as_metadata)
161
}
162
}
163
-
164
-
#[async_trait::async_trait]
165
-
impl<T: OAuthResolver + Sync + Send> OAuthResolver for std::sync::Arc<T> {}
166
167
pub async fn resolve_authorization_server<T: HttpClient + ?Sized>(
168
client: &T,
···
1
use crate::types::{OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata};
2
use http::{Request, StatusCode};
3
use jacquard_common::IntoStatic;
4
use jacquard_common::types::did_doc::DidDocument;
5
use jacquard_common::types::ident::AtIdentifier;
6
use jacquard_common::{http_client::HttpClient, types::did::Did};
7
+
use jacquard_identity::resolver::{IdentityError, IdentityResolver};
8
use url::Url;
9
10
#[derive(thiserror::Error, Debug, miette::Diagnostic)]
···
159
Ok(as_metadata)
160
}
161
}
162
163
pub async fn resolve_authorization_server<T: HttpClient + ?Sized>(
164
client: &T,
+2
-1
crates/jacquard-oauth/src/session.rs
+2
-1
crates/jacquard-oauth/src/session.rs
+1
-2
crates/jacquard-oauth/src/utils.rs
+1
-2
crates/jacquard-oauth/src/utils.rs
···
1
use base64::Engine;
2
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
3
use elliptic_curve::SecretKey;
4
-
use jacquard_common::{CowStr, IntoStatic, cowstr::ToCowStr};
5
use jose_jwk::{Key, crypto};
6
use rand::{CryptoRng, RngCore, rngs::ThreadRng};
7
use sha2::{Digest, Sha256};
8
-
use smol_str::ToSmolStr;
9
use std::cmp::Ordering;
10
11
use crate::{FALLBACK_ALG, types::OAuthAuthorizationServerMetadata};
···
1
use base64::Engine;
2
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
3
use elliptic_curve::SecretKey;
4
+
use jacquard_common::CowStr;
5
use jose_jwk::{Key, crypto};
6
use rand::{CryptoRng, RngCore, rngs::ThreadRng};
7
use sha2::{Digest, Sha256};
8
use std::cmp::Ordering;
9
10
use crate::{FALLBACK_ALG, types::OAuthAuthorizationServerMetadata};
+2
-2
crates/jacquard/Cargo.toml
+2
-2
crates/jacquard/Cargo.toml
···
16
derive = ["dep:jacquard-derive"]
17
api = ["jacquard-api/com_atproto"]
18
api_all = ["api", "jacquard-api/app_bsky", "jacquard-api/chat_bsky", "jacquard-api/tools_ozone"]
19
-
dns = ["dep:hickory-resolver", "jacquard-common/dns"]
20
fancy = ["miette/fancy"]
21
loopback = ["dep:rouille"]
22
···
47
serde_json.workspace = true
48
thiserror.workspace = true
49
tokio = { version = "1", features = ["macros", "rt-multi-thread", "fs"] }
50
-
hickory-resolver = { version = "0.24", default-features = false, features = ["system-config", "tokio-runtime"], optional = true }
51
url.workspace = true
52
smol_str.workspace = true
53
percent-encoding = "2"
···
56
p256 = { version = "0.13", features = ["ecdsa"] }
57
rand_core = "0.6"
58
rouille = { version = "3.6.2", optional = true }
···
16
derive = ["dep:jacquard-derive"]
17
api = ["jacquard-api/com_atproto"]
18
api_all = ["api", "jacquard-api/app_bsky", "jacquard-api/chat_bsky", "jacquard-api/tools_ozone"]
19
+
dns = ["jacquard-identity/dns"]
20
fancy = ["miette/fancy"]
21
loopback = ["dep:rouille"]
22
···
47
serde_json.workspace = true
48
thiserror.workspace = true
49
tokio = { version = "1", features = ["macros", "rt-multi-thread", "fs"] }
50
url.workspace = true
51
smol_str.workspace = true
52
percent-encoding = "2"
···
55
p256 = { version = "0.13", features = ["ecdsa"] }
56
rand_core = "0.6"
57
rouille = { version = "3.6.2", optional = true }
58
+
jacquard-identity = { version = "0.2.0", path = "../jacquard-identity" }
+3
-5
crates/jacquard/src/client.rs
+3
-5
crates/jacquard/src/client.rs
···
21
pub use token::FileTokenStore;
22
use url::Url;
23
24
-
use p256::SecretKey;
25
-
26
// Note: Stateless and stateful XRPC clients are implemented in xrpc_call.rs and at_client.rs
27
28
pub(crate) const NSID_REFRESH_SESSION: &str = "com.atproto.server.refreshSession";
···
133
#[derive(Debug, Clone)]
134
pub enum AuthSession {
135
AppPassword(AtpSession),
136
-
OAuth(jacquard_oauth::session::OauthSession<'static>),
137
}
138
139
impl AuthSession {
···
187
}
188
}
189
190
-
impl From<jacquard_oauth::session::OauthSession<'static>> for AuthSession {
191
-
fn from(session: jacquard_oauth::session::OauthSession<'static>) -> Self {
192
AuthSession::OAuth(session)
193
}
194
}
···
21
pub use token::FileTokenStore;
22
use url::Url;
23
24
// Note: Stateless and stateful XRPC clients are implemented in xrpc_call.rs and at_client.rs
25
26
pub(crate) const NSID_REFRESH_SESSION: &str = "com.atproto.server.refreshSession";
···
131
#[derive(Debug, Clone)]
132
pub enum AuthSession {
133
AppPassword(AtpSession),
134
+
OAuth(jacquard_oauth::session::ClientSessionData<'static>),
135
}
136
137
impl AuthSession {
···
185
}
186
}
187
188
+
impl From<jacquard_oauth::session::ClientSessionData<'static>> for AuthSession {
189
+
fn from(session: jacquard_oauth::session::ClientSessionData<'static>) -> Self {
190
AuthSession::OAuth(session)
191
}
192
}
+1
-1
crates/jacquard/src/client/at_client.rs
+1
-1
crates/jacquard/src/client/at_client.rs
+11
-10
crates/jacquard/src/identity.rs
crates/jacquard-identity/src/lib.rs
+11
-10
crates/jacquard/src/identity.rs
crates/jacquard-identity/src/lib.rs
···
12
//! and optionally validate the document `id` against the requested DID.
13
14
// use crate::CowStr; // not currently needed directly here
15
16
use bytes::Bytes;
17
-
use jacquard_common::IntoStatic;
18
use jacquard_common::error::TransportError;
19
use jacquard_common::http_client::HttpClient;
20
-
use jacquard_common::ident_resolver::{
21
-
DidDocResponse, DidStep, HandleStep, IdentityError, IdentityResolver, MiniDoc, PlcSource,
22
-
ResolverOptions,
23
-
};
24
use jacquard_common::types::xrpc::XrpcExt;
25
use percent_encoding::percent_decode_str;
26
use reqwest::StatusCode;
27
use url::{ParseError, Url};
28
-
29
-
use crate::api::com_atproto::identity::{resolve_did, resolve_handle::ResolveHandle};
30
-
use crate::types::did_doc::DidDocument;
31
-
use crate::types::ident::AtIdentifier;
32
-
use crate::types::string::{Did, Handle};
33
34
#[cfg(feature = "dns")]
35
use hickory_resolver::{TokioAsyncResolver, config::ResolverConfig};
···
12
//! and optionally validate the document `id` against the requested DID.
13
14
// use crate::CowStr; // not currently needed directly here
15
+
pub mod resolver;
16
17
+
use crate::resolver::{
18
+
DidDocResponse, DidStep, HandleStep, IdentityError, IdentityResolver, MiniDoc, PlcSource,
19
+
ResolverOptions,
20
+
};
21
use bytes::Bytes;
22
+
use jacquard_api::com_atproto::identity::resolve_did;
23
+
use jacquard_api::com_atproto::identity::resolve_handle::ResolveHandle;
24
use jacquard_common::error::TransportError;
25
use jacquard_common::http_client::HttpClient;
26
+
use jacquard_common::types::did::Did;
27
+
use jacquard_common::types::did_doc::DidDocument;
28
+
use jacquard_common::types::ident::AtIdentifier;
29
use jacquard_common::types::xrpc::XrpcExt;
30
+
use jacquard_common::{IntoStatic, types::string::Handle};
31
use percent_encoding::percent_decode_str;
32
use reqwest::StatusCode;
33
use url::{ParseError, Url};
34
35
#[cfg(feature = "dns")]
36
use hickory_resolver::{TokioAsyncResolver, config::ResolverConfig};
+1
-2
crates/jacquard/src/lib.rs
+1
-2
crates/jacquard/src/lib.rs
+1
-1
crates/jacquard/src/main.rs
+1
-1
crates/jacquard/src/main.rs
···
3
use jacquard::api::app_bsky::feed::get_timeline::GetTimeline;
4
use jacquard::api::com_atproto::server::create_session::CreateSession;
5
use jacquard::client::{AtpSession, AuthSession, BasicClient};
6
-
use jacquard::ident_resolver::IdentityResolver;
7
use jacquard::identity::slingshot_resolver_default;
8
use jacquard::types::string::Handle;
9
use miette::IntoDiagnostic;
···
3
use jacquard::api::app_bsky::feed::get_timeline::GetTimeline;
4
use jacquard::api::com_atproto::server::create_session::CreateSession;
5
use jacquard::client::{AtpSession, AuthSession, BasicClient};
6
+
use jacquard::identity::resolver::IdentityResolver;
7
use jacquard::identity::slingshot_resolver_default;
8
use jacquard::types::string::Handle;
9
use miette::IntoDiagnostic;