Skip to main content

solid_pod_rs/
lib.rs

1//! Framework-agnostic Rust library for serving Solid Protocol 0.11 pods.
2//!
3//! `solid-pod-rs` provides LDP resource and container semantics, Web Access
4//! Control (WAC 1.x + 2.0), WebID profile documents, Solid-OIDC 0.1,
5//! NIP-98 HTTP auth, and Solid Notifications 0.2 -- all without coupling
6//! to a specific HTTP framework. Wire it into actix-web, axum, hyper, or
7//! anything else; the crate never mounts routes itself.
8//!
9//! For a turnkey binary, use the sibling crate
10//! [`solid-pod-rs-server`](https://docs.rs/solid-pod-rs-server).
11//!
12//! ## Feature flags
13//!
14//! | Flag | Default | Purpose |
15//! |-------------------------|:-------:|-----------------------------------------------|
16//! | `core` | off | Pure-logic surfaces only — wasm32 / CF Workers. |
17//! | `std` | on | std lib (always; reserved for future no_std).  |
18//! | `tokio-runtime` | on | Tokio + tokio-tungstenite + futures-util.       |
19//! | `notifications` | on | WebSocketChannel2023 + WebhookChannel2023.      |
20//! | `fs-backend` | on | POSIX filesystem storage. |
21//! | `memory-backend` | on | In-process `HashMap` storage (tests/demos). |
22//! | `s3-backend` | off | AWS S3 / S3-compatible object stores. |
23//! | `oidc` | off | Solid-OIDC 0.1 + DPoP. |
24//! | `dpop-replay-cache` | off | DPoP `jti` replay cache (pulls `oidc`). |
25//! | `nip98-schnorr` | off | BIP-340 signature verification for NIP-98. |
26//! | `acl-origin` | off | WAC `acl:origin` enforcement. |
27//! | `security-primitives` | off | SSRF guard + dotfile allowlist. |
28//! | `legacy-notifications` | off | `solid-0.1` WebSocket adapter (SolidOS). |
29//! | `config-loader` | off | Layered config loader with `JSS_*` env vars. |
30//! | `webhook-signing` | off | RFC 9421 Ed25519 webhook signing. |
31//! | `did-nostr-types` | off | Canonical did:nostr types (wasm32-safe). |
32//! | `did-nostr` | off | did:nostr resolver in `interop`. |
33//! | `rate-limit` | off | Sliding-window LRU rate limiter. |
34//! | `quota` | off | Per-pod `.quota.json` sidecar (atomic writes). |
35//! | `mrc20` | off | BIP-341 taproot key chaining for MRC20 tokens. |
36//! | `lws-cid` | off | LWS 1.0 CID self-signed JWT verifier (ES256K). |
37//! | `lws-cid-p256` | off | LWS-CID + ES256 (P-256) algorithm. |
38//! | `lws-cid-eddsa` | off | LWS-CID + EdDSA (Ed25519) algorithm. |
39//! | `lws-cid-full` | off | LWS-CID with all algorithms. |
40//!
41//! `core` consumers wire the crate via `default-features = false,
42//! features = ["core"]` and get only the pure-logic surfaces (no
43//! tokio, no reqwest, no DNS resolver, no filesystem). See
44//! `RELEASE_NOTES.md` v0.4.0-alpha.3 for the absorbed surfaces map.
45//!
46//! ## Module overview
47//!
48//! | Module | Responsibility |
49//! |-----------------|--------------------------------------------------------------|
50//! | [`storage`] | `Storage` trait + FS / Memory / S3 backends. |
51//! | [`ldp`] | Resources, containers, content negotiation, PATCH, `Prefer`. |
52//! | [`wac`] | Access control evaluator + WAC 2.0 conditions framework. |
53//! | [`webid`] | WebID profile documents (emits `solid:oidcIssuer` + CID). |
54//! | [`mashlib`] | SolidOS data-browser HTML wrapper + data-island embed.    |
55//! | [`auth`] | NIP-98 HTTP auth + LWS-CID self-signed JWT verifier. |
56//! | [`payments`] | HTTP 402, Web Ledgers, multi-chain TXO, payment store. |
57//! | [`mrc20`] | MRC20 state chains, JCS, BIP-341 key chaining.       |
58//! | [`trading`] | Peer-to-peer order book + AMM constant-product pool.  |
59//! | [`notifications`] | WebSocket, Webhook (RFC 9421 signed), legacy adapter. |
60//! | [`error`] | Crate-wide [`PodError`] error type. |
61//! | [`config`] | Layered configuration schema. |
62//! | [`security`] | SSRF guard, dotfile allowlist, CORS, rate limiter. |
63//! | [`quota`] | Per-pod byte-quota enforcement. |
64//! | [`multitenant`] | `PodResolver` trait; path + subdomain modes. |
65//! | [`interop`] | `.well-known/solid`, WebFinger, NodeInfo, did:nostr. |
66//! | [`did_nostr_types`] | Canonical `did:nostr` types (wasm32-safe, `core`). |
67//! | [`provision`] | Pod bootstrap (WebID + containers + type indexes + ACL). |
68//!
69//! ## Quick start
70//!
71//! ```rust,no_run
72//! use solid_pod_rs::storage::memory::MemoryBackend;
73//! use solid_pod_rs::{Storage, evaluate_access, AccessMode};
74//! use bytes::Bytes;
75//! use std::sync::Arc;
76//!
77//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
78//! // 1. Create a storage backend.
79//! let store = Arc::new(MemoryBackend::new());
80//!
81//! // 2. PUT a resource.
82//! store.put("/hello.txt", Bytes::from("world"), "text/plain").await.unwrap();
83//!
84//! // 3. GET it back.
85//! let (body, meta) = store.get("/hello.txt").await.unwrap();
86//! assert_eq!(&body[..], b"world");
87//! assert_eq!(meta.content_type, "text/plain");
88//!
89//! // 4. WAC evaluation (no ACL document = deny by default).
90//! let allowed = evaluate_access(None, Some("https://alice.example/profile/card#me"),
91//!     "/hello.txt", AccessMode::Read, None);
92//! assert!(!allowed);
93//! # });
94//! ```
95//!
96//! ## Attribution
97//!
98//! Rust port of JavaScriptSolidServer. See NOTICE for provenance.
99
100#![doc = include_str!("../README.md")]
101#![deny(unsafe_code)]
102#![warn(rust_2018_idioms)]
103
104// ---------------------------------------------------------------------------
105// Always-compiled (`core`) modules.
106//
107// Pure-logic surfaces: parsers, validators, type definitions. None of
108// these reach for tokio, reqwest, or notify directly. Wasm32 / CF
109// Workers consumers wire these via
110// `default-features = false, features = ["core"]`.
111// ---------------------------------------------------------------------------
112pub mod auth;
113pub mod config;
114pub mod error;
115pub mod interop;
116pub mod ldp;
117pub mod mashlib;
118pub mod metrics;
119pub mod mrc20;
120pub mod multitenant;
121pub mod payments;
122pub mod security;
123pub mod trading;
124pub mod wac;
125pub mod webid;
126
127// ---------------------------------------------------------------------------
128// `did-nostr-types`-gated module.
129//
130// Canonical did:nostr types (NostrPubkey, DID-Doc renderers, ServiceEntry)
131// behind a lightweight feature flag. No runtime deps — wasm32 / CF Workers
132// consumers get these via `core`.
133// ---------------------------------------------------------------------------
134#[cfg(feature = "did-nostr-types")]
135pub mod did_nostr_types;
136
137// ---------------------------------------------------------------------------
138// `tokio-runtime`-gated modules.
139//
140// These pull tokio (mpsc, fs, broadcast) or reqwest (HTTP client) and
141// are unavailable to `core` consumers. They are wired in by the
142// `default` feature set so the existing surface from 0.4.0-alpha.2 is
143// preserved bit-for-bit on native builds.
144// ---------------------------------------------------------------------------
145#[cfg(feature = "notifications")]
146pub mod notifications;
147#[cfg(feature = "tokio-runtime")]
148pub mod provision;
149#[cfg(feature = "tokio-runtime")]
150pub mod quota;
151#[cfg(feature = "tokio-runtime")]
152pub mod storage;
153
154#[cfg(feature = "oidc")]
155pub mod oidc;
156
157/// Transport-agnostic HTTP / WebSocket handler drivers. Consumers wire
158/// these into their HTTP framework of choice. Feature-gated; present
159/// only when at least one handler is enabled. Respects the F7
160/// library-server boundary — this crate never mounts routes itself.
161#[cfg(feature = "legacy-notifications")]
162pub mod handlers;
163
164// ---------------------------------------------------------------------------
165// `core` re-exports — always available.
166// ---------------------------------------------------------------------------
167pub use auth::nip98::Nip98Verifier;
168pub use auth::self_signed::{
169    CidVerifier, ProofEnvelope, SelfSignedError, SelfSignedVerifier, VerifiedSubject,
170};
171pub use error::PodError;
172pub use interop::{
173    dev_session, nip05_document, verify_nip05, webfinger_response, well_known_solid, DevSession,
174    Nip05Document, SolidWellKnown, WebFingerJrd, WebFingerLink,
175};
176pub use ldp::{
177    apply_json_patch, apply_n3_patch, apply_patch_to_absent, apply_sparql_patch, cache_control_for,
178    evaluate_preconditions, is_rdf_content_type, link_headers, negotiate_format, not_found_headers,
179    options_for, parse_range_header, parse_range_header_v2, patch_dialect_from_mime,
180    server_managed_triples, slice_range, vary_header, ByteRange, ConditionalOutcome,
181    ContainerRepresentation, Graph, OptionsResponse, PatchCreateOutcome, PatchDialect,
182    PatchOutcome, PreferHeader, RangeOutcome, RdfFormat, Term, Triple, ACCEPT_PATCH, ACCEPT_POST,
183    CACHE_CONTROL_RDF, SPARQL_UPDATE_MAX_BYTES,
184};
185pub use mashlib::{MashlibConfig, MashlibMode, DATA_ISLAND_MAX_BYTES};
186pub use metrics::SecurityMetrics;
187pub use multitenant::{PathResolver, PodResolver, ResolvedPath, SubdomainResolver};
188pub use security::{is_path_allowed, DotfileAllowlist, DotfileError, DotfilePathError};
189pub use wac::{
190    check_origin, evaluate_access, evaluate_access_with_groups, extract_origin_patterns,
191    method_to_mode, mode_name, parse_turtle_acl, serialize_turtle_acl, wac_allow_header,
192    AccessMode, AclDocument, GroupMembership, Origin, OriginDecision, OriginPattern,
193    StaticGroupMembership,
194};
195pub use webid::{
196    extract_oidc_issuer, generate_webid_html, generate_webid_html_with_issuer, validate_webid_html,
197};
198
199// ---------------------------------------------------------------------------
200// `tokio-runtime`-gated re-exports.
201// ---------------------------------------------------------------------------
202#[cfg(feature = "tokio-runtime")]
203pub use provision::{
204    check_admin_override, provision_pod, AdminOverride, ProvisionOutcome, ProvisionPlan,
205    QuotaTracker,
206};
207#[cfg(feature = "quota")]
208pub use quota::FsQuotaStore;
209#[cfg(feature = "tokio-runtime")]
210pub use quota::{QuotaExceeded, QuotaPolicy, QuotaUsage};
211#[cfg(feature = "tokio-runtime")]
212pub use security::{is_safe_url, resolve_and_check, IpClass, SsrfError, SsrfPolicy};
213#[cfg(feature = "tokio-runtime")]
214pub use storage::{ResourceMeta, Storage, StorageEvent};