commit 85abda4da9ffd76f4967ac61df519d5095172a81
parent a8cbaf8f98fd0a7d4e0232feefc2c3bf005f853f
Author: triesap <tyson@radroots.org>
Date: Tue, 14 Jul 2026 18:36:44 +0000
contract: retire legacy event operation names
- replace retired event names in the public operations contract
- align synthetic operation fixtures with target-state event and wire names
- reject retired event names in operation contract validation
- validate with contract and xtask contract test lanes
Diffstat:
2 files changed, 123 insertions(+), 29 deletions(-)
diff --git a/contracts/operations.toml b/contracts/operations.toml
@@ -16,12 +16,12 @@ domains = [
[shared_types]
public = [
- "WireEventParts",
- "RadrootsFrozenEventDraft",
+ "RadrootsNip01EventWireParts",
+ "RadrootsEventDraft",
"RadrootsSignedEvent",
- "RadrootsNostrEvent",
- "RadrootsNostrEventRef",
- "RadrootsNostrEventPtr",
+ "RadrootsEventEnvelope",
+ "RadrootsEventRef",
+ "RadrootsEventPtr",
"RadrootsListingAddress",
"RadrootsProfile",
"RadrootsFarm",
@@ -86,7 +86,7 @@ domain = "profile"
id = "profile.build_draft"
stability = "beta"
inputs = ["RadrootsProfile", "RadrootsProfileType?"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -104,7 +104,7 @@ domain = "farm"
id = "farm.build_draft"
stability = "beta"
inputs = ["RadrootsFarm"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -143,7 +143,7 @@ domain = "listing"
id = "listing.build_draft"
stability = "beta"
inputs = ["RadrootsListing"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -163,7 +163,7 @@ vector = "contracts/conformance/vectors/listing/build_draft.v1.json"
domain = "listing"
id = "listing.parse_event"
stability = "beta"
-inputs = ["RadrootsNostrEvent"]
+inputs = ["RadrootsEventEnvelope"]
outputs = ["RadrootsListing"]
error_class = "parse_error"
deterministic = true
@@ -173,7 +173,7 @@ transport = "native"
[operations.listing_parse_event.implementation]
rust_modules = ["crates/trade/src/listing/codec.rs"]
rust_types = [
- "radroots_event::RadrootsNostrEvent",
+ "radroots_event::RadrootsEventEnvelope",
"radroots_event::listing::RadrootsListing",
]
@@ -310,8 +310,8 @@ vector = "contracts/conformance/vectors/social/mvp.v1.json"
domain = "order"
id = "order.build_order_request_draft"
stability = "beta"
-inputs = ["RadrootsOrderRequest", "RadrootsNostrEventPtr"]
-outputs = ["WireEventParts"]
+inputs = ["RadrootsOrderRequest", "RadrootsEventPtr"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -320,7 +320,7 @@ transport = "native"
[operations.order_build_order_request_draft.implementation]
rust_modules = ["crates/event_codec/src/order/encode.rs"]
rust_types = [
- "radroots_event::RadrootsNostrEventPtr",
+ "radroots_event::RadrootsEventPtr",
"radroots_event::order::RadrootsOrderRequest",
]
@@ -332,7 +332,7 @@ domain = "order"
id = "order.build_order_decision_draft"
stability = "beta"
inputs = ["root_event_id", "prev_event_id", "RadrootsOrderDecision"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -349,7 +349,7 @@ vector = "contracts/conformance/vectors/order/build_order_decision_draft.v1.json
domain = "order"
id = "order.parse_order_request"
stability = "beta"
-inputs = ["RadrootsNostrEvent"]
+inputs = ["RadrootsEventEnvelope"]
outputs = ["RadrootsOrderEnvelope", "RadrootsOrderRequest"]
error_class = "parse_error"
deterministic = true
@@ -359,7 +359,7 @@ transport = "native"
[operations.order_parse_order_request.implementation]
rust_modules = ["crates/event_codec/src/order/decode.rs"]
rust_types = [
- "radroots_event::RadrootsNostrEvent",
+ "radroots_event::RadrootsEventEnvelope",
"radroots_event::order::RadrootsOrderEnvelope",
"radroots_event::order::RadrootsOrderRequest",
]
@@ -371,7 +371,7 @@ vector = "contracts/conformance/vectors/order/parse_order_request.v1.json"
domain = "order"
id = "order.parse_order_decision"
stability = "beta"
-inputs = ["RadrootsNostrEvent"]
+inputs = ["RadrootsEventEnvelope"]
outputs = ["RadrootsOrderEnvelope", "RadrootsOrderDecision"]
error_class = "parse_error"
deterministic = true
@@ -381,7 +381,7 @@ transport = "native"
[operations.order_parse_order_decision.implementation]
rust_modules = ["crates/event_codec/src/order/decode.rs"]
rust_types = [
- "radroots_event::RadrootsNostrEvent",
+ "radroots_event::RadrootsEventEnvelope",
"radroots_event::order::RadrootsOrderEnvelope",
"radroots_event::order::RadrootsOrderDecision",
]
@@ -411,7 +411,7 @@ vector = "contracts/conformance/vectors/order/parse_listing_address.v1.json"
domain = "trade_validation"
id = "trade_validation.validate_listing_event"
stability = "beta"
-inputs = ["RadrootsNostrEvent"]
+inputs = ["RadrootsEventEnvelope"]
outputs = ["TradeListingValidateResult"]
error_class = "validation_error"
deterministic = true
@@ -421,7 +421,7 @@ transport = "native"
[operations.trade_validation_validate_listing_event.implementation]
rust_modules = ["crates/trade/src/listing/validation.rs"]
rust_types = [
- "radroots_event::RadrootsNostrEvent",
+ "radroots_event::RadrootsEventEnvelope",
"radroots_trade::listing::validation::RadrootsTradeListing",
]
@@ -452,7 +452,7 @@ vector = "contracts/conformance/vectors/knowledge/manifest_and_decode.v1.json"
domain = "knowledge"
id = "knowledge.verify_and_decode_event"
stability = "beta"
-inputs = ["RadrootsNostrEvent"]
+inputs = ["RadrootsEventEnvelope"]
outputs = ["RadrootsDecodedEvent"]
error_class = "decode_error"
deterministic = true
@@ -465,7 +465,7 @@ rust_modules = [
"crates/event_codec/src/knowledge/decode.rs",
]
rust_types = [
- "radroots_event::RadrootsNostrEvent",
+ "radroots_event::RadrootsEventEnvelope",
"radroots_event_codec::verification::RadrootsDecodedEvent",
]
diff --git a/tools/xtask/src/contract.rs b/tools/xtask/src/contract.rs
@@ -46,6 +46,13 @@ const DTO_TOOLING_DEPENDENCIES: [&str; 4] = [
"dto_bindgen_core",
"dto_bindgen_macros",
];
+const RETIRED_OPERATION_EVENT_NAMES: [&str; 5] = [
+ "WireEventParts",
+ "RadrootsFrozenEventDraft",
+ "RadrootsNostrEvent",
+ "RadrootsNostrEventRef",
+ "RadrootsNostrEventPtr",
+];
const EVENT_BOUNDARY_MATRIX_RELATIVES: [&str; 1] = [
"docs/platform/canonical/open_source/radroots_v1_spec/02_public_contract_and_runtime/08_event_boundary_matrix.md",
];
@@ -2791,6 +2798,10 @@ fn validate_operations_contract(
if shared_types.is_empty() {
return Err("shared_types.public must not be empty".to_string());
}
+ validate_no_retired_operation_event_names(
+ &operations_manifest.shared_types.public,
+ "shared_types.public",
+ )?;
let error_classes =
collect_non_empty_set(&operations_manifest.errors.classes, "errors.classes")?;
if error_classes.is_empty() {
@@ -2864,6 +2875,10 @@ fn validate_operations_contract(
&operation.inputs,
&format!("operation {} inputs", operation.id),
)?;
+ validate_no_retired_operation_event_names(
+ &operation.inputs,
+ &format!("operation {} inputs", operation.id),
+ )?;
if operation.outputs.is_empty() {
return Err(format!(
"operation {} outputs must not be empty",
@@ -2874,6 +2889,10 @@ fn validate_operations_contract(
&operation.outputs,
&format!("operation {} outputs", operation.id),
)?;
+ validate_no_retired_operation_event_names(
+ &operation.outputs,
+ &format!("operation {} outputs", operation.id),
+ )?;
if !error_classes.contains(&operation.error_class) {
return Err(format!(
"operation {} references unknown error class {}",
@@ -2896,6 +2915,10 @@ fn validate_operations_contract(
&operation.implementation.rust_types,
&format!("operation {} implementation.rust_types", operation.id),
)?;
+ validate_no_retired_operation_event_names(
+ &operation.implementation.rust_types,
+ &format!("operation {} implementation.rust_types", operation.id),
+ )?;
for rust_module in &operation.implementation.rust_modules {
if rust_module.trim().is_empty() {
return Err(format!(
@@ -2941,6 +2964,22 @@ fn validate_operations_contract(
Ok(())
}
+fn validate_no_retired_operation_event_names(
+ values: &[String],
+ context: &str,
+) -> Result<(), String> {
+ for value in values {
+ for retired in RETIRED_OPERATION_EVENT_NAMES {
+ if value == retired || value.ends_with(&format!("::{retired}")) {
+ return Err(format!(
+ "{context} uses retired event type {retired}; use target-state event and wire names"
+ ));
+ }
+ }
+ }
+ Ok(())
+}
+
fn package_field_configured(table: &toml::value::Table, field: &str) -> bool {
let Some(value) = table.get(field) else {
return false;
@@ -4354,12 +4393,12 @@ domains = ["profile", "farm", "listing", "trade"]
[shared_types]
public = [
- "WireEventParts",
- "RadrootsFrozenEventDraft",
+ "RadrootsNip01EventWireParts",
+ "RadrootsEventDraft",
"RadrootsSignedEvent",
- "RadrootsNostrEvent",
- "RadrootsNostrEventRef",
- "RadrootsNostrEventPtr",
+ "RadrootsEventEnvelope",
+ "RadrootsEventRef",
+ "RadrootsEventPtr",
"RadrootsListingAddress",
"RadrootsProfile",
"RadrootsFarm",
@@ -4378,7 +4417,7 @@ domain = "profile"
id = "profile.build_draft"
stability = "beta"
inputs = ["RadrootsProfile", "RadrootsProfileType?"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -4396,7 +4435,7 @@ domain = "listing"
id = "listing.build_draft"
stability = "beta"
inputs = ["RadrootsListing"]
-outputs = ["WireEventParts"]
+outputs = ["RadrootsNip01EventWireParts"]
error_class = "encode_error"
deterministic = true
signing = "native"
@@ -5985,6 +6024,61 @@ rust_package = "radroots_sdk"
.domains
.clear();
});
+ assert_bundle_error(
+ "shared_types.public uses retired event type RadrootsNostrEvent",
+ |bundle| {
+ bundle
+ .operations_manifest
+ .as_mut()
+ .expect("operations manifest")
+ .shared_types
+ .public
+ .push("RadrootsNostrEvent".to_string());
+ },
+ );
+ assert_bundle_error(
+ "operation profile.build_draft inputs uses retired event type RadrootsNostrEvent",
+ |bundle| {
+ bundle
+ .operations_manifest
+ .as_mut()
+ .expect("operations manifest")
+ .operations
+ .get_mut("profile_build_draft")
+ .expect("profile operation")
+ .inputs
+ .push("RadrootsNostrEvent".to_string());
+ },
+ );
+ assert_bundle_error(
+ "operation profile.build_draft outputs uses retired event type WireEventParts",
+ |bundle| {
+ bundle
+ .operations_manifest
+ .as_mut()
+ .expect("operations manifest")
+ .operations
+ .get_mut("profile_build_draft")
+ .expect("profile operation")
+ .outputs
+ .push("WireEventParts".to_string());
+ },
+ );
+ assert_bundle_error(
+ "operation profile.build_draft implementation.rust_types uses retired event type RadrootsNostrEventPtr",
+ |bundle| {
+ bundle
+ .operations_manifest
+ .as_mut()
+ .expect("operations manifest")
+ .operations
+ .get_mut("profile_build_draft")
+ .expect("profile operation")
+ .implementation
+ .rust_types
+ .push("radroots_event::RadrootsNostrEventPtr".to_string());
+ },
+ );
let _ = fs::remove_dir_all(root);
}