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:
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()
+}