lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 19521ad129c89393401eba44f27d415d2b7308e1
parent 9600081e87d5f8de95260f683039a889bd50aa0e
Author: triesap <tyson@radroots.org>
Date:   Fri, 31 Jul 2026 16:41:56 +0000

nostr-connect: align package manifest and module root

- declare the exact serde feature vocabulary and required Radroots graph
- add the approved server module to the public package skeleton
- hide the publish-frozen prelude until its scheduled consumer cutover
- enforce package identity dependencies and module shape with boundary tests

Diffstat:
MCargo.lock | 4++++
Mcrates/nostr_connect/Cargo.toml | 12++++++++++++
Mcrates/nostr_connect/src/lib.rs | 4++++
Acrates/nostr_connect/src/server.rs | 5+++++
Acrates/nostr_connect/tests/package_boundary.rs | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -4743,6 +4743,10 @@ name = "radroots_nostr_connect" version = "0.1.0-alpha" dependencies = [ "nostr", + "radroots_event", + "radroots_identity", + "radroots_nostr", + "radroots_protocol", "serde", "serde_json", "thiserror 1.0.69", diff --git a/crates/nostr_connect/Cargo.toml b/crates/nostr_connect/Cargo.toml @@ -15,7 +15,19 @@ readme = "README.md" [lib] name = "radroots_nostr_connect" +[features] +default = ["serde"] +serde = [ + "radroots_event/serde", + "radroots_identity/serde", + "radroots_protocol/serde", +] + [dependencies] +radroots_event = { workspace = true, default-features = false } +radroots_identity = { workspace = true, default-features = false } +radroots_nostr = { workspace = true, default-features = false } +radroots_protocol = { workspace = true, default-features = false } nostr = { workspace = true, features = ["std", "nip44"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/crates/nostr_connect/src/lib.rs b/crates/nostr_connect/src/lib.rs @@ -6,8 +6,12 @@ pub mod error; pub mod message; pub mod method; pub mod permission; +pub mod server; pub mod uri; +// Transitional compatibility surface for consumers migrated in Step 141. +// Publication remains disabled, and Step 143 removes this module. +#[doc(hidden)] pub mod prelude { pub use crate::client::{ RadrootsNostrConnectClientEventOutcome, RadrootsNostrConnectClientProgress, diff --git a/crates/nostr_connect/src/server.rs b/crates/nostr_connect/src/server.rs @@ -0,0 +1,5 @@ +//! NIP-46 server-side protocol state. +//! +//! The protocol-owned server state machine is introduced in Step 138. Host +//! approval policy, persistence, and relay execution remain outside this +//! module and outside the package charter. diff --git a/crates/nostr_connect/tests/package_boundary.rs b/crates/nostr_connect/tests/package_boundary.rs @@ -0,0 +1,85 @@ +use std::collections::BTreeSet; + +const MANIFEST: &str = include_str!("../Cargo.toml"); +const ROOT: &str = include_str!("../src/lib.rs"); +const SERVER: &str = include_str!("../src/server.rs"); + +#[test] +fn manifest_has_final_identity_feature_vocabulary_and_radroots_dependencies() { + for required in [ + "name = \"radroots_nostr_connect\"", + "version = \"0.1.0-alpha\"", + "publish = false", + "[lib]\nname = \"radroots_nostr_connect\"", + "default = [\"serde\"]", + "radroots_event = { workspace = true, default-features = false }", + "radroots_identity = { workspace = true, default-features = false }", + "radroots_nostr = { workspace = true, default-features = false }", + "radroots_protocol = { workspace = true, default-features = false }", + ] { + assert!( + MANIFEST.contains(required), + "manifest is missing `{required}`" + ); + } + + assert_eq!( + table_keys(MANIFEST, "[features]"), + BTreeSet::from(["default", "serde"]) + ); + assert_eq!( + table_keys(MANIFEST, "[dependencies]") + .into_iter() + .filter(|dependency| dependency.starts_with("radroots_")) + .collect::<BTreeSet<_>>(), + BTreeSet::from([ + "radroots_event", + "radroots_identity", + "radroots_nostr", + "radroots_protocol", + ]) + ); +} + +#[test] +fn crate_root_contains_the_approved_module_skeleton() { + for module in [ + "client", + "error", + "message", + "method", + "permission", + "server", + "uri", + ] { + assert!( + ROOT.contains(&format!("pub mod {module};")), + "crate root is missing `{module}`" + ); + } + + assert!(SERVER.starts_with("//! NIP-46 server-side protocol state.")); + assert!(ROOT.contains("#[doc(hidden)]\npub mod prelude")); + assert!( + ROOT.contains("Step 143 removes this module"), + "the temporary prelude must carry an exact removal checkpoint" + ); +} + +fn table_keys<'a>(source: &'a str, header: &str) -> BTreeSet<&'a str> { + let Some((_, tail)) = source.split_once(header) else { + panic!("manifest is missing {header}"); + }; + + tail.lines() + .skip(1) + .take_while(|line| !line.trim_start().starts_with('[')) + .filter_map(|line| { + let line = line.trim(); + if line.is_empty() || line.starts_with('#') || line.starts_with('"') { + return None; + } + line.split_once('=').map(|(key, _)| key.trim()) + }) + .collect() +}