Skip to main content

dig_urn_resolver/
lib.rs

1//! # dig-urn-resolver
2//!
3//! Resolve a DIG URN to its data through the protocol, node-first.
4//!
5//! Given a `urn:dig:chia:<store_id>[:<root>]/<resource_key>[?salt=<hex>]`, this
6//! crate returns the resource's bytes + content type, following the canonical §5.3
7//! ladder — **explicit override > `dig.local` > `localhost:9778` > `rpc.dig.net`** —
8//! and using the first tier that responds:
9//!
10//! * **node tier** (`GET /s/<storeId>[:<root>]/<path>`) — a local dig-node decrypts
11//!   + verifies server-side under a loopback trust boundary and returns plaintext.
12//! * **rpc tier** (`dig.getContent`) — a blind fetch of opaque ciphertext +
13//!   inclusion proofs from the untrusted public gateway, VERIFIED against the
14//!   URN's PINNED root and decrypted client-side (fail-closed). The trust root is
15//!   NEVER taken from the gateway; a rootless URN is rejected on this tier.
16//!
17//! ## Reuse, not reimplementation
18//! All read-crypto (URN canonicalization + retrieval-key derivation, merkle
19//! inclusion verify, AES-256-GCM-SIV open) is `digstore_core`'s — the same
20//! functions the browser read-crypto and the on-chain crates share — so this crate
21//! can never skew from the canonical crypto. It adds only the ladder, the injected
22//! transport, content-type derivation, fail-closed assembly, and the wasm glue.
23//!
24//! ## Outcomes
25//! A resolve returns `Result<`[`ResolveOutcome`]`, `[`ResolveError`]`>` — three
26//! distinct outcomes, never conflated:
27//! * [`ResolveOutcome::Success`] — verified, decrypted content.
28//! * [`ResolveOutcome::IntegrityFailure`] — bytes were fetched but failed merkle/
29//!   decrypt verification (tampered / decoy / wrong root). A hard, fail-CLOSED
30//!   SECURITY outcome — the unverified bytes are NEVER returned. `resolveObjectUrl`
31//!   renders a branded "Integrity Verification Failed" page, never the bytes.
32//! * [`ResolveOutcome::Unreachable`] — every tier was down; nothing fetched. A
33//!   friendly, retryable "connect a node" page.
34//!
35//! A malformed URN, a not-found resource, and a reachable rpc protocol error are
36//! hard [`ResolveError`]s.
37//!
38//! ## First consumer
39//! Sage wallet NFT images: an NFT `data`-uri that is a root-pinned DIG URN →
40//! `resolveObjectUrl(urn)` (wasm) → an object URL usable as an `<img src>`, working
41//! with no dig-node running (rpc fallback) and faster when a node is present.
42
43pub mod cache;
44pub mod content_type;
45pub mod crypto;
46pub mod error;
47pub mod images;
48pub mod ladder;
49pub mod node;
50#[cfg(all(feature = "wasm", not(feature = "native")))]
51pub mod node_fs;
52pub mod pages;
53pub mod resolver;
54pub mod rpc;
55pub mod transport;
56pub mod urn;
57
58pub use error::{ResolveError, Result};
59pub use ladder::{
60    Endpoint, EndpointKind, DIG_LOCAL_BASE, DIG_NODE_PORT, LOCALHOST_BASE, RPC_DEFAULT_BASE,
61};
62pub use pages::DEFAULT_CONNECT_URL;
63pub use resolver::{ResolveOptions, ResolveOutcome, ResolvedData, Resolver};
64pub use transport::{HttpResponse, HttpTransport, TransportError};
65pub use urn::ParsedUrn;
66
67#[cfg(feature = "native")]
68pub mod native;
69
70#[cfg(feature = "wasm")]
71pub mod wasm;
72
73/// The crate version (matches `Cargo.toml`), for compatibility checks.
74pub fn version() -> &'static str {
75    env!("CARGO_PKG_VERSION")
76}