From 8b41f64e1285157974efcd797031ddd0ebbd6f5f Mon Sep 17 00:00:00 2001 From: Mollusk Date: Sat, 25 Jul 2026 20:06:06 -0400 Subject: [PATCH] host/observer: tag the live prop-recovery row with the real wire value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verification-round follow-up to 1b01847. The phase-3r live row proves carrier 1 survives the bind, which is the property F1 destroyed — but it tagged its fixture sink with `peerspeak.owned=true`, not the `1` the contract pins and peerspeak actually emits. It would have passed even if the real literal did not. Adds PEERSPEAK_OWNED_VALUE so the fixture can name the producer's value, and asserts it against the shared contract file alongside the other two literals. The sink's name still deliberately avoids the `peerspeak_owned_` prefix, so carrier 2 cannot stand in for carrier 1 in that row. Co-Authored-By: Claude Opus 5 --- src/host/observer/adapter.rs | 10 +++++++++- src/host/taint/mod.rs | 9 +++++++++ src/host/taint/tests.rs | 7 ++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/host/observer/adapter.rs b/src/host/observer/adapter.rs index ef6302e..387bb26 100644 --- a/src/host/observer/adapter.rs +++ b/src/host/observer/adapter.rs @@ -898,7 +898,15 @@ mod tests { "module-null-sink", &[ format!("sink_name={unique}"), - "sink_properties=peerspeak.owned=true node.passthrough=true".to_string(), + // The value peerspeak actually emits, not merely a truthy one: + // this row is the live proof that carrier 1 survives the bind, + // and the sink's name deliberately does *not* carry the + // `peerspeak_owned_` prefix, so carrier 2 cannot stand in for + // it here. + format!( + "sink_properties={PEERSPEAK_OWNED_PROP}={} node.passthrough=true", + crate::host::taint::PEERSPEAK_OWNED_VALUE + ), ], ); let null_sink_id = null_sink.id.expect("null-sink module must have an id"); diff --git a/src/host/taint/mod.rs b/src/host/taint/mod.rs index 4c4e9b4..2479be6 100644 --- a/src/host/taint/mod.rs +++ b/src/host/taint/mod.rs @@ -136,6 +136,15 @@ pub const ECHO_CANCEL_GROUP_PREFIX: &str = "echo-cancel-"; /// change that invalidates the phase 5 matrix. pub const PEERSPEAK_OWNED_PROP: &str = "peerspeak.owned"; +/// The value peerspeak emits for [`PEERSPEAK_OWNED_PROP`]. +/// +/// The consumer deliberately accepts **any** truthy value, not just this one +/// (see the observer's `truthy`) — treating an unexpected value as "owned" is +/// the fail-closed direction. This constant exists so live tests can tag a +/// node with exactly what the producer sends, rather than something merely +/// truthy that would pass even if the real literal did not. +pub const PEERSPEAK_OWNED_VALUE: &str = "1"; + /// Ownership carrier 2: a `node.name` prefix (v3.5 §5.1, round 8). /// /// Matched as a **union** with [`PEERSPEAK_OWNED_PROP`] — either one makes a diff --git a/src/host/taint/tests.rs b/src/host/taint/tests.rs index 0c4faa2..10df0c4 100644 --- a/src/host/taint/tests.rs +++ b/src/host/taint/tests.rs @@ -251,10 +251,11 @@ fn ownership_carriers_match_the_cross_repo_fixture() { assert_eq!(super::PEERSPEAK_OWNED_PROP, get("prop_key")); assert_eq!(super::PEERSPEAK_OWNED_NODE_PREFIX, get("node_name_prefix")); + assert_eq!(super::PEERSPEAK_OWNED_VALUE, get("prop_value")); - // The value the producer pins must be one this consumer reads as truthy. - // `truthy` lives at the observer boundary; assert the property of it that - // matters here rather than reaching across modules for the function. + // …and that value must be one this consumer reads as truthy. `truthy` + // lives at the observer boundary; assert the property of it that matters + // here rather than reaching across modules for the function. let value = get("prop_value"); assert!( value != "false" && value != "0",