pub struct RegistryClient { /* private fields */ }Expand description
HTTP client for a single ACDP registry.
reqwest::Client clones cheaply (it’s an Arc internally), so this
struct is Clone to enable per-authority caching in
crate::CrossRegistryResolver without re-wiring HTTP+TLS
state on every hop.
Implementations§
Source§impl RegistryClient
impl RegistryClient
The authority (host, plus port when non-default) of the registry
this client talks to — the value a receipt’s registry_did
must match (RFC-ACDP-0010 serving-authority cross-check).
Sourcepub fn new(base_url: &str) -> Result<Self, AcdpError>
pub fn new(base_url: &str) -> Result<Self, AcdpError>
Connect to a registry at base_url (e.g. https://registry.example.com).
Uses rustls for TLS; does not use the system OpenSSL. Applies
the RFC-ACDP-0006 §7.4 default timeouts (5s connect, 30s total)
and §7.5 redirect policy (max 3 follows, same authority only).
§DNS-rebinding posture (default)
This constructor installs the SafeDnsResolver DNS hook
(RFC-ACDP-0006 §7.6): every hostname lookup — the first connect,
each redirect, and every reconnect the pool makes over the
client’s lifetime — is filtered through the SsrfPolicy at
DNS time, before any TCP connect. This is strictly stronger
than pin-once resolution (Self::new_pinned): a pinned
client validates a single answer and reuses that address, so a
hostile authoritative DNS server that only later flips a name
into a forbidden range is still caught here but not there. The
DNS-hook posture is therefore the default for all callers; reach
for Self::builder only when you need a non-default knob (a
private root cert, a custom SsrfPolicy, timeout overrides, or
the legacy pinned mode).
Sourcepub fn builder(base_url: &str) -> RegistryClientBuilder
pub fn builder(base_url: &str) -> RegistryClientBuilder
Start a RegistryClientBuilder for the non-default connection
postures — a private root certificate, a custom SsrfPolicy,
timeout overrides, and the legacy pinned-resolution mode.
The builder’s default is identical to Self::new: the
stronger SafeDnsResolver DNS-hook posture with the default
SSRF policy and the RFC-ACDP-0006 §7.4 timeouts. Opt into
pin-once resolution with RegistryClientBuilder::pinned.
Sourcepub async fn new_pinned(
base_url: &str,
policy: &SsrfPolicy,
) -> Result<Self, AcdpError>
👎Deprecated since 0.4.0: prefer RegistryClient::new (SafeDnsResolver DNS hook — validates every connection, strictly stronger than pin-once) or, for explicit pin-once mode, RegistryClient::builder(base_url).pinned(true).ssrf_policy(policy).build().await
pub async fn new_pinned( base_url: &str, policy: &SsrfPolicy, ) -> Result<Self, AcdpError>
prefer RegistryClient::new (SafeDnsResolver DNS hook — validates every connection, strictly stronger than pin-once) or, for explicit pin-once mode, RegistryClient::builder(base_url).pinned(true).ssrf_policy(policy).build().await
Connect to a registry with pin-once DNS-rebinding protection (RFC-ACDP-0006 §7.6).
Resolves the hostname once, validates the resolved IP against
policy, then pins that IP into the HTTP client.
Deprecated: the default Self::new posture installs the
SafeDnsResolver DNS hook, which validates the resolved IP on
every connection (including reconnects) rather than just once —
strictly stronger protection. For the rare case that still wants
pin-once semantics with a custom policy, use
RegistryClient::builder(base_url).pinned(true).ssrf_policy(policy).build().await.
Sourcepub async fn capabilities(&self) -> Result<CapabilitiesDocument, AcdpError>
pub async fn capabilities(&self) -> Result<CapabilitiesDocument, AcdpError>
Fetch the registry’s capabilities document and run the
RFC-ACDP-0007 §3 runtime validation
(acdp_validation::validate_capabilities).
Body capped at 64 KB per RFC-ACDP-0006 §7.3.
Sourcepub async fn capabilities_with_ttl(
&self,
) -> Result<(CapabilitiesDocument, Duration), AcdpError>
pub async fn capabilities_with_ttl( &self, ) -> Result<(CapabilitiesDocument, Duration), AcdpError>
Like Self::capabilities but also returns the cache TTL
derived from the response’s Cache-Control: max-age=N header.
Per RFC-ACDP-0006 §4.2, consumers SHOULD cache the capabilities
document for min(max-age, 3600s) seconds. When no
Cache-Control (or no parseable max-age) is returned, the
fallback is 300s — a conservative middle-ground that matches
crate::ResolverOptions::capabilities_ttl’s default.
Sourcepub async fn publish(
&self,
req: &PublishRequest,
) -> Result<PublishResponse, AcdpError>
pub async fn publish( &self, req: &PublishRequest, ) -> Result<PublishResponse, AcdpError>
Publish a context. Returns the registry-assigned identifiers.
Sourcepub async fn publish_idempotent(
&self,
req: &PublishRequest,
idempotency_key: &str,
) -> Result<PublishResponse, AcdpError>
pub async fn publish_idempotent( &self, req: &PublishRequest, idempotency_key: &str, ) -> Result<PublishResponse, AcdpError>
Publish with an idempotency key for safe retries.
Sourcepub async fn publish_with_retry(
&self,
req: &PublishRequest,
idempotency_key: &str,
max_attempts: u32,
) -> Result<PublishResponse, AcdpError>
pub async fn publish_with_retry( &self, req: &PublishRequest, idempotency_key: &str, max_attempts: u32, ) -> Result<PublishResponse, AcdpError>
Publish with bounded retry for transient failures.
Reuses idempotency_key across attempts so the registry can
dedupe (RFC-ACDP-0003 §6). Retries only when the error is
transient per AcdpError::is_transient. Bounded backoff:
250 ms, 500 ms, 1 s, 2 s.
Sourcepub async fn retrieve(&self, ctx_id: &CtxId) -> Result<FullContext, AcdpError>
pub async fn retrieve(&self, ctx_id: &CtxId) -> Result<FullContext, AcdpError>
Retrieve a full context (body + registry_state) by ctx_id.
Body capped at 1 MB per RFC-ACDP-0006 §7.3.
Sourcepub async fn retrieve_with_metadata(
&self,
ctx_id: &CtxId,
) -> Result<(FullContext, RetrievalMetadata), AcdpError>
pub async fn retrieve_with_metadata( &self, ctx_id: &CtxId, ) -> Result<(FullContext, RetrievalMetadata), AcdpError>
Retrieve a full context plus cache / integrity headers.
Sourcepub async fn retrieve_if_none_match(
&self,
ctx_id: &CtxId,
etag: &str,
) -> Result<Option<(FullContext, RetrievalMetadata)>, AcdpError>
pub async fn retrieve_if_none_match( &self, ctx_id: &CtxId, etag: &str, ) -> Result<Option<(FullContext, RetrievalMetadata)>, AcdpError>
Conditional retrieval using If-None-Match.
Returns Ok(None) when the registry responds 304 Not Modified.
Returns Ok(Some((body, metadata))) for a fresh retrieval.
Sourcepub async fn retrieve_body(&self, ctx_id: &CtxId) -> Result<Body, AcdpError>
pub async fn retrieve_body(&self, ctx_id: &CtxId) -> Result<Body, AcdpError>
Retrieve just the body (immutable, highly cacheable).
Sourcepub async fn lineage(
&self,
lineage_id: &LineageId,
) -> Result<Vec<FullContext>, AcdpError>
pub async fn lineage( &self, lineage_id: &LineageId, ) -> Result<Vec<FullContext>, AcdpError>
Retrieve all contexts in a lineage (oldest to newest).
Sourcepub async fn current(
&self,
lineage_id: &LineageId,
) -> Result<FullContext, AcdpError>
pub async fn current( &self, lineage_id: &LineageId, ) -> Result<FullContext, AcdpError>
Retrieve the current (latest) context in a lineage.
Sourcepub async fn search(
&self,
params: &SearchParams,
) -> Result<SearchResponse, AcdpError>
pub async fn search( &self, params: &SearchParams, ) -> Result<SearchResponse, AcdpError>
Keyword search across the registry.
Body capped at 64 KB (search responses are projection-summaries — IMP-03: not the 1 MB context cap).
Sourcepub fn search_builder(&self) -> RegistrySearch<'_>
pub fn search_builder(&self) -> RegistrySearch<'_>
Begin a fluent search via RegistrySearch. Chains parameters
with strong typing, then .send().await issues the request.
let resp = client
.search_builder()
.q("market risk")
.tag("risk")
.tag("portfolio")
.limit(50)
.send()
.await?;Trait Implementations§
Source§impl Clone for RegistryClient
impl Clone for RegistryClient
Source§fn clone(&self) -> RegistryClient
fn clone(&self) -> RegistryClient
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more