commit cd92bb6b9df4b75730bffdb96cebdccb52a1f990
parent 244be2aef850a3f1df20b1be7903ed8967a82315
Author: triesap <tyson@radroots.org>
Date: Fri, 31 Jul 2026 20:11:02 +0000
nostr-connect: complete package conformance coverage
- enforce exact production dependencies and approved root exports
- compile-check the final client, server, error, and transport surface
- quarantine the temporary compatibility trait through Step 143
- verify native, wasm, feature, test, docs, and architecture matrices
Diffstat:
1 file changed, 122 insertions(+), 14 deletions(-)
diff --git a/crates/nostr_connect/tests/package_boundary.rs b/crates/nostr_connect/tests/package_boundary.rs
@@ -1,5 +1,10 @@
use std::collections::BTreeSet;
+use radroots_nostr_connect::{
+ BunkerUri, Client, ClientUri, Error, Method, Permission, Request, Response, Server,
+ client::Transport,
+};
+
const MANIFEST: &str = include_str!("../Cargo.toml");
const CLIENT: &str = include_str!("../src/client.rs");
const METHOD: &str = include_str!("../src/method.rs");
@@ -43,24 +48,74 @@ fn manifest_has_final_identity_feature_vocabulary_and_radroots_dependencies() {
"radroots_protocol",
])
);
-}
-
-#[test]
-fn crate_root_contains_the_approved_module_skeleton() {
- for module in [
- "client",
- "error",
- "message",
- "method",
- "permission",
- "server",
- "uri",
+ assert_eq!(
+ table_keys(MANIFEST, "[dependencies]"),
+ BTreeSet::from([
+ "nostr",
+ "radroots_event",
+ "radroots_identity",
+ "radroots_nostr",
+ "radroots_protocol",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "url",
+ ])
+ );
+ assert_eq!(
+ table_keys(MANIFEST, "[dev-dependencies]"),
+ BTreeSet::from(["tokio"])
+ );
+ for forbidden in [
+ "keyring",
+ "nostr-sdk",
+ "reqwest",
+ "sqlx",
+ "radroots_secrets",
+ "radroots_storage",
+ "radroots_transport_nostr",
] {
assert!(
- ROOT.contains(&format!("pub mod {module};")),
- "crate root is missing `{module}`"
+ !table_keys(MANIFEST, "[dependencies]").contains(forbidden),
+ "protocol package acquired forbidden production dependency `{forbidden}`"
);
}
+}
+
+#[test]
+fn crate_root_contains_the_approved_module_skeleton() {
+ let final_root = ROOT
+ .split("// Transitional compatibility surface")
+ .next()
+ .expect("final root declarations");
+ assert_eq!(
+ declarations(final_root, "pub mod "),
+ BTreeSet::from([
+ "client",
+ "error",
+ "message",
+ "method",
+ "permission",
+ "server",
+ "uri",
+ ])
+ );
+ assert_eq!(
+ final_root
+ .lines()
+ .map(str::trim)
+ .filter(|line| line.starts_with("pub use "))
+ .collect::<BTreeSet<_>>(),
+ BTreeSet::from([
+ "pub use client::Client;",
+ "pub use error::RadrootsNostrConnectError as Error;",
+ "pub use message::{Request, Response};",
+ "pub use method::Method;",
+ "pub use permission::Permission;",
+ "pub use server::Server;",
+ "pub use uri::{BunkerUri, ClientUri};",
+ ])
+ );
assert!(SERVER.starts_with("//! Relay- and persistence-independent NIP-46 server state."));
assert!(ROOT.contains("pub use server::Server;"));
@@ -72,6 +127,48 @@ fn crate_root_contains_the_approved_module_skeleton() {
}
#[test]
+fn approved_root_exports_and_transport_trait_compile() {
+ fn assert_value<T: Send + Sync>() {}
+ fn assert_error<T: core::error::Error + Send + Sync>() {}
+ fn accept_transport(_: &mut dyn Transport) {}
+
+ assert_value::<BunkerUri>();
+ assert_value::<Client>();
+ assert_value::<ClientUri>();
+ assert_value::<Method>();
+ assert_value::<Permission>();
+ assert_value::<Request>();
+ assert_value::<Response>();
+ assert_value::<Server>();
+ assert_error::<Error>();
+ let _ = accept_transport;
+
+ let public_traits = CLIENT
+ .lines()
+ .map(str::trim)
+ .filter(|line| line.starts_with("pub trait "))
+ .collect::<BTreeSet<_>>();
+ assert_eq!(
+ public_traits,
+ BTreeSet::from([
+ "pub trait RadrootsNostrConnectClientTransport {",
+ "pub trait Transport: Send {",
+ ]),
+ "only the final host transport SPI and Step 143 compatibility trait may remain"
+ );
+ for forbidden in [
+ "Relay", "Runtime", "Session", "Storage", "Secret", "Approval",
+ ] {
+ assert!(
+ public_traits
+ .iter()
+ .all(|trait_line| !trait_line.contains(forbidden)),
+ "protocol package exposes forbidden owner trait containing `{forbidden}`"
+ );
+ }
+}
+
+#[test]
fn uri_method_and_permission_types_use_canonical_owners_and_names() {
for root_export in [
"pub use method::Method;",
@@ -159,3 +256,14 @@ fn table_keys<'a>(source: &'a str, header: &str) -> BTreeSet<&'a str> {
})
.collect()
}
+
+fn declarations<'a>(source: &'a str, prefix: &str) -> BTreeSet<&'a str> {
+ source
+ .lines()
+ .map(str::trim)
+ .filter_map(|line| {
+ line.strip_prefix(prefix)
+ .and_then(|name| name.strip_suffix(';'))
+ })
+ .collect()
+}