commit 14417d787b2a9216fc32c156972b21f515699f29
parent 37b664841acf4f2fb052ec6ae3b139448a454a1b
Author: triesap <tyson@radroots.org>
Date: Mon, 3 Aug 2026 12:43:16 +0000
facade: add safe convenience builders
- Add deterministic memory and explicit local-only ordinary construction.
- Provide inert transport, NIP-46, native, daemon, and model feature helpers.
- Keep resources caller-owned and perform I/O only in the explicit native open.
- Record the single reviewed SDK API addition required by the facade default.
Diffstat:
7 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/crates/radroots/Cargo.toml b/crates/radroots/Cargo.toml
@@ -28,7 +28,7 @@ radroots_transport = { workspace = true }
[features]
default = ["client"]
-client = []
+client = ["radroots_sdk/memory"]
native = ["client"]
nostr = ["client"]
nip46 = ["nostr"]
diff --git a/crates/radroots/src/client.rs b/crates/radroots/src/client.rs
@@ -1 +1,66 @@
//! Curated client construction and operation entry points.
+
+#[cfg(feature = "nostr")]
+use std::sync::Arc;
+
+#[cfg(feature = "nostr")]
+use radroots_transport::{EventSink, EventSource};
+
+use crate::{ClientBuilder, transport::Profile};
+
+/// Creates the safe ordinary client builder with deterministic in-process
+/// storage and no transport, signer, runtime, worker, or file authority.
+#[must_use]
+pub fn memory() -> ClientBuilder {
+ ClientBuilder::memory_default()
+}
+
+/// Returns the explicit no-transport profile used by ordinary local work.
+#[must_use]
+pub const fn local_only() -> Profile {
+ Profile::local_only()
+}
+
+/// Adds caller-owned source and sink capabilities without connecting them or
+/// selecting a fallback transport.
+#[cfg(feature = "nostr")]
+#[must_use]
+pub fn with_transport(
+ builder: ClientBuilder,
+ source: Arc<dyn EventSource>,
+ sink: Arc<dyn EventSink>,
+) -> ClientBuilder {
+ builder.source(source).sink(sink)
+}
+
+/// Adds an explicitly constructed NIP-46 signer provider.
+#[cfg(feature = "nip46")]
+#[must_use]
+pub fn with_nip46_signer(
+ builder: ClientBuilder,
+ provider: crate::signing::Provider,
+) -> ClientBuilder {
+ builder.signing(provider)
+}
+
+/// Explicitly opens validated native SQLite storage.
+#[cfg(feature = "native")]
+pub async fn native(options: crate::storage::SqliteOptions) -> crate::Result<ClientBuilder> {
+ ClientBuilder::sqlite(options).await
+}
+
+/// Reports whether the concrete GeoNames capability was selected at compile
+/// time. Asset inspection, acquisition, and database opening remain explicit.
+#[cfg(feature = "geonames")]
+#[must_use]
+pub const fn geonames_enabled() -> bool {
+ true
+}
+
+/// Reports whether canonical knowledge contracts were selected at compile
+/// time. Merely selecting the feature performs no event or storage operation.
+#[cfg(feature = "knowledge")]
+#[must_use]
+pub const fn knowledge_enabled() -> bool {
+ true
+}
diff --git a/crates/radroots/src/storage.rs b/crates/radroots/src/storage.rs
@@ -1,3 +1,6 @@
//! Curated storage entry points.
pub use radroots_sdk::storage::{IntegrityStatus, Operations, Status};
+
+#[cfg(feature = "native")]
+pub use radroots_sdk::storage::{SqliteOpenMode, SqliteOptions, SqlitePaths};
diff --git a/crates/radroots/src/transport.rs b/crates/radroots/src/transport.rs
@@ -2,6 +2,9 @@
pub use radroots_sdk::transport::Profile;
pub use radroots_transport::{
- Error, Target, TargetSet, TransportId,
+ Error, EventSink, EventSource, Target, TargetSet, TransportId,
policy::{SatisfactionClass, SatisfactionPolicy, TargetPolicy},
};
+
+#[cfg(feature = "radrootsd")]
+pub use radroots_sdk::transport::{DaemonAuth, DaemonConfig, DaemonDelivery, DaemonError};
diff --git a/crates/radroots/tests/public_surface.rs b/crates/radroots/tests/public_surface.rs
@@ -34,6 +34,14 @@ fn canonical_domain_paths_compile() {
};
}
+#[cfg(feature = "client")]
+#[test]
+fn ordinary_memory_and_local_only_construction_is_inert() {
+ let client = radroots::client::memory().build().expect("memory client");
+ assert!(!client.is_closed());
+ assert!(radroots::client::local_only().is_local_only());
+}
+
#[cfg(feature = "knowledge")]
#[test]
fn canonical_knowledge_paths_compile() {
diff --git a/crates/sdk/src/client.rs b/crates/sdk/src/client.rs
@@ -70,6 +70,18 @@ impl ClientBuilder {
Self::new().storage(Arc::new(MemoryStorage::new(generation)))
}
+ /// Creates the ordinary deterministic in-process memory configuration.
+ ///
+ /// This performs no I/O and is intended for ephemeral local clients whose
+ /// source-generation identity does not need to survive the process. Hosts
+ /// that persist cursors should call [`Self::memory`] with their own
+ /// generation instead.
+ #[cfg(feature = "memory")]
+ #[must_use]
+ pub fn memory_default() -> Self {
+ Self::new().storage(Arc::new(MemoryStorage::default()))
+ }
+
/// Explicitly opens canonical SQLite storage from validated host-owned
/// configuration and returns a builder containing only the storage SPI.
#[cfg(feature = "sqlite")]
diff --git a/docs/api/radroots_sdk-0.1.0-alpha.txt b/docs/api/radroots_sdk-0.1.0-alpha.txt
@@ -68,6 +68,7 @@ impl radroots_sdk::client::ClientBuilder
pub fn radroots_sdk::client::ClientBuilder::build(self) -> radroots_sdk::error::Result<radroots_sdk::client::Client>
pub fn radroots_sdk::client::ClientBuilder::capability_availability(self, radroots_sdk::capability::CapabilityId, radroots_sdk::capability::Availability) -> Self
pub fn radroots_sdk::client::ClientBuilder::memory(radroots_storage::event::SourceGeneration) -> Self
+pub fn radroots_sdk::client::ClientBuilder::memory_default() -> Self
pub fn radroots_sdk::client::ClientBuilder::new() -> Self
pub fn radroots_sdk::client::ClientBuilder::signer(self, alloc::sync::Arc<dyn radroots_signing::signer::Signer>) -> Self
pub fn radroots_sdk::client::ClientBuilder::signing(self, radroots_sdk::signing::Provider) -> Self
@@ -337,6 +338,7 @@ impl radroots_sdk::client::ClientBuilder
pub fn radroots_sdk::client::ClientBuilder::build(self) -> radroots_sdk::error::Result<radroots_sdk::client::Client>
pub fn radroots_sdk::client::ClientBuilder::capability_availability(self, radroots_sdk::capability::CapabilityId, radroots_sdk::capability::Availability) -> Self
pub fn radroots_sdk::client::ClientBuilder::memory(radroots_storage::event::SourceGeneration) -> Self
+pub fn radroots_sdk::client::ClientBuilder::memory_default() -> Self
pub fn radroots_sdk::client::ClientBuilder::new() -> Self
pub fn radroots_sdk::client::ClientBuilder::signer(self, alloc::sync::Arc<dyn radroots_signing::signer::Signer>) -> Self
pub fn radroots_sdk::client::ClientBuilder::signing(self, radroots_sdk::signing::Provider) -> Self