From b3a0e57de8d8553c75bfc13a76106fdd6a380316 Mon Sep 17 00:00:00 2001 From: mfw78 Date: Tue, 21 Jul 2026 23:19:10 +0000 Subject: [PATCH] feat(nexum-runtime): reject colliding extension claims at boot One boot-time uniqueness pass fails fast on a service namespace, subscription kind, or manifest section two wired extensions both claim, each of which silently dedupes downstream. --- crates/nexum-runtime/src/supervisor.rs | 32 ++++++++++ crates/nexum-runtime/src/supervisor/tests.rs | 62 ++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/crates/nexum-runtime/src/supervisor.rs b/crates/nexum-runtime/src/supervisor.rs index fd369eeb..ebddddd8 100644 --- a/crates/nexum-runtime/src/supervisor.rs +++ b/crates/nexum-runtime/src/supervisor.rs @@ -365,6 +365,36 @@ fn enforce_extension_sections( Ok(()) } +/// Refuse a string two wired extensions both claim, fail-fast at boot, in +/// any of three classes: service namespace, subscription kind, manifest +/// section. Each class dedupes silently downstream, so an unchecked +/// collision routes to whichever extension the map or `.any()` scan hits +/// first. +fn enforce_extension_uniqueness( + extensions: &[Arc>], +) -> Result<()> { + let mut namespaces = BTreeSet::new(); + let mut kinds = BTreeSet::new(); + let mut sections = BTreeSet::new(); + for ext in extensions { + let namespace = ext.namespace(); + if !namespaces.insert(namespace) { + return Err(anyhow!("extension namespace {namespace} is claimed twice")); + } + for kind in ext.subscriptions() { + if !kinds.insert(*kind) { + return Err(anyhow!("subscription kind {kind} is claimed twice")); + } + } + for section in ext.manifest_sections() { + if !sections.insert(*section) { + return Err(anyhow!("manifest section [{section}] is claimed twice")); + } + } + } + Ok(()) +} + /// Insert one kind row, refusing a duplicate manifest spelling. fn register_kind( kinds: &mut ProviderKinds, @@ -395,6 +425,7 @@ impl Supervisor { extensions: &[Arc>], clocks: Option, ) -> Result { + enforce_extension_uniqueness(extensions)?; let registry = capability_registry(extensions); let services = HostServices::from_extensions(extensions)?; // Provider kinds the boot loop resolves manifest kinds against. @@ -489,6 +520,7 @@ impl Supervisor { extensions: &[Arc>], clocks: Option, ) -> Result { + enforce_extension_uniqueness(extensions)?; let registry = capability_registry(extensions); let services = HostServices::from_extensions(extensions)?; let entry = ModuleEntry { diff --git a/crates/nexum-runtime/src/supervisor/tests.rs b/crates/nexum-runtime/src/supervisor/tests.rs index 2617869f..947a17fc 100644 --- a/crates/nexum-runtime/src/supervisor/tests.rs +++ b/crates/nexum-runtime/src/supervisor/tests.rs @@ -63,6 +63,68 @@ fn extension_sections_must_be_claimed() { assert!(err.to_string().contains("keeper"), "{err}"); } +/// Two extensions colliding on a subscription kind or a manifest section +/// are refused at boot; a non-colliding set passes the uniqueness pass. +#[test] +fn extension_claims_must_be_unique() { + struct Claiming { + namespace: &'static str, + subscriptions: &'static [&'static str], + sections: &'static [&'static str], + } + impl Extension for Claiming { + fn namespace(&self) -> &'static str { + self.namespace + } + fn capabilities(&self) -> crate::manifest::NamespaceCaps { + crate::manifest::NamespaceCaps { + prefix: "acme:ext/", + ifaces: &[], + } + } + fn link(&self, _linker: &mut Linker>) -> anyhow::Result<()> { + Ok(()) + } + fn subscriptions(&self) -> &'static [&'static str] { + self.subscriptions + } + fn manifest_sections(&self) -> &'static [&'static str] { + self.sections + } + } + fn ext( + namespace: &'static str, + subscriptions: &'static [&'static str], + sections: &'static [&'static str], + ) -> Arc> { + Arc::new(Claiming { + namespace, + subscriptions, + sections, + }) + } + + enforce_extension_uniqueness(&[ + ext("a", &["orders"], &["venue"]), + ext("b", &["fills"], &["pool"]), + ]) + .expect("non-colliding set boots"); + + let err = enforce_extension_uniqueness(&[ + ext("a", &["orders"], &["venue"]), + ext("b", &["orders"], &["pool"]), + ]) + .expect_err("duplicate subscription kind"); + assert!(err.to_string().contains("orders"), "{err}"); + + let err = enforce_extension_uniqueness(&[ + ext("a", &["orders"], &["venue"]), + ext("b", &["fills"], &["venue"]), + ]) + .expect_err("duplicate manifest section"); + assert!(err.to_string().contains("[venue]"), "{err}"); +} + #[tokio::test] async fn empty_supervisor_returns_no_subscriptions() { let engine = make_wasmtime_engine();