lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit f53d11a551b3efad4a337bd24d28e4bbffa8c8e5
parent 3563f3b5a4331eb2cb3f925cafc9de524d844228
Author: triesap <tyson@radroots.org>
Date:   Thu, 20 Aug 2026 16:02:49 +0000

events: retire prototype validation receipt

- remove kind 3440 from active event, protocol, registry, and binding surfaces
- preserve fail-closed rejection for the retired numeric and textual identities
- refresh generated registries, bindings, inventories, and the public API baseline
- bind canonical and packaged protocol inventories to one freshness generator

Diffstat:
Mcontracts/api_baselines/radroots_event.txt | 11+----------
Mcontracts/codegen/protocol_v1.inventory.json | 2+-
Mcontracts/codegen/protocol_v1.inventory.sha256 | 2+-
Mcontracts/codegen/protocol_v1.toml | 1+
Mcontracts/event_boundary_matrix.md | 1-
Mcontracts/event_store/event_contract_registry_v7.inventory.json | 53-----------------------------------------------------
Mcontracts/event_store/event_contract_registry_v7.inventory.sha256 | 2+-
Mcrates/event/src/contract/registry_v7.rs | 40+---------------------------------------
Mcrates/event/src/kinds.rs | 82+++++--------------------------------------------------------------------------
Mcrates/event/tests/source_boundary.rs | 44++++++++++++++++++++++++++++++++++++++++++++
Mcrates/event_bindings/src/model.rs | 4----
Mcrates/event_bindings/tests/fixtures/generated_kinds.ts | 2--
Mcrates/protocol/src/event/v1.rs | 37+++++++++++++++++++++++++++++--------
Mcrates/protocol/tests/fixtures/protocol_v1.inventory.json | 2+-
Mtools/xtask/src/contract.rs | 19+------------------
Mtools/xtask/src/generate/protocol.rs | 22++++++++++++++++++++++
16 files changed, 108 insertions(+), 216 deletions(-)

diff --git a/contracts/api_baselines/radroots_event.txt b/contracts/api_baselines/radroots_event.txt @@ -574,7 +574,7 @@ pub mod radroots_event::envelope pub mod radroots_event::envelope::event_head pub mod radroots_event::envelope::kind pub const radroots_event::envelope::kind::CLASSIFIED_LISTING_EVENT_KINDS: [u32; 1] -pub const radroots_event::envelope::kind::COMMERCIAL_EVENT_KINDS: [u32; 7] +pub const radroots_event::envelope::kind::COMMERCIAL_EVENT_KINDS: [u32; 6] pub const radroots_event::envelope::kind::EVENTS_CANDIDATE_KINDS: [u32; 4] pub const radroots_event::envelope::kind::HOME_FEED_CANDIDATE_KINDS: [u32; 9] pub const radroots_event::envelope::kind::KIND_ACCOUNT_CLAIM: u32 @@ -682,7 +682,6 @@ pub const radroots_event::envelope::kind::KIND_TRADE_PROPOSAL: u32 pub const radroots_event::envelope::kind::KIND_TRADE_REVISION_DECISION: u32 pub const radroots_event::envelope::kind::KIND_TRADE_REVISION_PROPOSAL: u32 pub const radroots_event::envelope::kind::KIND_TRADE_SELLER_RESERVATION_ASSERTION: u32 -pub const radroots_event::envelope::kind::KIND_TRADE_VALIDATION_RECEIPT: u32 pub const radroots_event::envelope::kind::KIND_VALIDATOR_SET: u32 pub const radroots_event::envelope::kind::KIND_WIKI_ARTICLE: u32 pub const radroots_event::envelope::kind::KIND_WIKI_MERGE_REQUEST: u32 @@ -703,7 +702,6 @@ pub const radroots_event::envelope::kind::PRODUCTION_SOCIAL_KINDS: [u32; 4] pub const radroots_event::envelope::kind::PROFILE_PUBLIC_CONTENT_KINDS: [u32; 8] pub const radroots_event::envelope::kind::PUBLIC_SOCIAL_KINDS: [u32; 12] pub const radroots_event::envelope::kind::TRADE_MUTATION_EVENT_KINDS: [u32; 5] -pub const radroots_event::envelope::kind::TRADE_VALIDATION_EVENT_KINDS: [u32; 1] pub const radroots_event::envelope::kind::UNAMBIGUOUS_PUBLIC_SOCIAL_KINDS: [u32; 11] pub const radroots_event::envelope::kind::WIKI_EVENT_KINDS: [u32; 3] pub const fn radroots_event::envelope::kind::is_ambiguous_public_social_kind(u32) -> bool @@ -732,17 +730,10 @@ pub const fn radroots_event::envelope::kind::is_public_social_kind(u32) -> bool pub const fn radroots_event::envelope::kind::is_request_kind(u32) -> bool pub const fn radroots_event::envelope::kind::is_result_kind(u32) -> bool pub const fn radroots_event::envelope::kind::is_trade_mutation_event_kind(u32) -> bool -pub const fn radroots_event::envelope::kind::is_trade_validation_event_kind(u32) -> bool -pub const fn radroots_event::envelope::kind::is_trade_validation_receipt_kind(u32) -> bool -pub const fn radroots_event::envelope::kind::is_trade_validation_service_event_kind(u32) -> bool -pub const fn radroots_event::envelope::kind::is_trade_validation_service_request_kind(u32) -> bool -pub const fn radroots_event::envelope::kind::is_trade_validation_service_result_kind(u32) -> bool pub const fn radroots_event::envelope::kind::is_unambiguous_public_social_kind(u32) -> bool pub const fn radroots_event::envelope::kind::is_wiki_event_kind(u32) -> bool pub const fn radroots_event::envelope::kind::request_kind_for_result_kind(u32) -> core::option::Option<u32> pub const fn radroots_event::envelope::kind::result_kind_for_request_kind(u32) -> core::option::Option<u32> -pub const fn radroots_event::envelope::kind::trade_validation_service_request_kind_for_result(u32) -> core::option::Option<u32> -pub const fn radroots_event::envelope::kind::trade_validation_service_result_kind_for_request(u32) -> core::option::Option<u32> pub enum radroots_event::envelope::EventEnvelopeError pub radroots_event::envelope::EventEnvelopeError::ContentTooLarge pub radroots_event::envelope::EventEnvelopeError::ContentTooLarge::actual: usize diff --git a/contracts/codegen/protocol_v1.inventory.json b/contracts/codegen/protocol_v1.inventory.json @@ -85,7 +85,7 @@ { "module": "event::v1", "path": "crates/protocol/src/event/v1.rs", - "sha256": "cc5b36e7e5cef0c7e375c2ce473267f5721994416d5154296a135890dface2e4", + "sha256": "9522617516b011e966cb7ee3c8f073b89fbd485e6c1776ad9ab65e563944daf3", "types": [ { "rust_path": "radroots_protocol::event::v1::EventClass", diff --git a/contracts/codegen/protocol_v1.inventory.sha256 b/contracts/codegen/protocol_v1.inventory.sha256 @@ -1 +1 @@ -f056d9398159b2b45aad1e3c47ce6d0bcee7400c65d88f843510f73673ddc6ac +239346a4d0f34c33f76cd06d3cda9a9df84e906c44474180cc139fb7712b7985 diff --git a/contracts/codegen/protocol_v1.toml b/contracts/codegen/protocol_v1.toml @@ -3,6 +3,7 @@ package = "radroots_protocol" source_hash_algorithm = "sha256_bytes_v1" inventory_path = "contracts/codegen/protocol_v1.inventory.json" inventory_sha256_path = "contracts/codegen/protocol_v1.inventory.sha256" +packaged_inventory_path = "crates/protocol/tests/fixtures/protocol_v1.inventory.json" [[source]] module = "capability::v1" diff --git a/contracts/event_boundary_matrix.md b/contracts/event_boundary_matrix.md @@ -315,7 +315,6 @@ not weaken or add effect fields to the request corpus. | trade:revision_proposal | 3472 | TradeMutationEnvelopeV1 | trade.get_trade, trade.list_trades, trade.propose_revision | buyer- or seller-authored complete replacement candidate referencing bounded parent heads | | trade:revision_decision | 3473 | TradeMutationEnvelopeV1 | trade.decide_candidate, trade.get_trade, trade.list_trades | exact accept or decline mutation for a referenced revision candidate and proposal mutation | | trade:cancellation | 3474 | TradeMutationEnvelopeV1 | trade.cancel_trade, trade.get_trade, trade.list_trades | policy-authorized cancellation mutation referencing the relevant candidate or current claim | -| trade:validation_receipt | 3440 | RadrootsTradeValidationReceipt | domains.trade.validation_receipt.get, domains.trade.validation_receipt.list, domains.trade.validation_receipt.verify | proof and inspection artifact around canonical signed trade events and deterministic reducer output; not buyer receipt state, payment state, order mutation, or trade authority | | relay_doc | N/A | RelayDocument | system.relay_doc.get | HTTP NIP-11 info via relay fetch helper | ## Membership list sets and claims diff --git a/contracts/event_store/event_contract_registry_v7.inventory.json b/contracts/event_store/event_contract_registry_v7.inventory.json @@ -1026,17 +1026,6 @@ }, { "ordinal": 92, - "kind": 3440, - "canonical_constant": "KIND_TRADE_VALIDATION_RECEIPT", - "name": "Trade Validation Receipt", - "class": "regular", - "standard": "radroots", - "accepted_event_contracts": [ - "radroots.trade.validation_receipt.v1" - ] - }, - { - "ordinal": 93, "kind": 3441, "canonical_constant": "KIND_RHI_EVIDENCE_ATTESTATION", "name": "RHI Evidence Attestation", @@ -5976,48 +5965,6 @@ "reducers": [ "trade_validation" ] - }, - { - "ordinal": 103, - "contract_id": "radroots.trade.validation_receipt.v1", - "kind": 3440, - "name": "Trade Validation Receipt", - "payload_type": "RadrootsTradeValidationReceipt", - "class": "regular", - "stability": "stable", - "privacy": "public", - "author_role": "service", - "content_schema": "json_object", - "authoring_policy": "generic_draft", - "discriminator": { - "type": "kind_only" - }, - "tags": [ - { - "name": "e", - "cardinality": "required_one", - "semantic": "root_event", - "value_type": "event_id", - "relay_indexed": true - }, - { - "name": "a", - "cardinality": "optional_one", - "semantic": "addressable_coordinate", - "value_type": "addressable_coordinate", - "relay_indexed": true - }, - { - "name": "output", - "cardinality": "required_one", - "semantic": "service_output", - "value_type": "text", - "relay_indexed": false - } - ], - "reducers": [ - "trade_validation" - ] } ] } diff --git a/contracts/event_store/event_contract_registry_v7.inventory.sha256 b/contracts/event_store/event_contract_registry_v7.inventory.sha256 @@ -1 +1 @@ -a449519d0c5f88845fe48458f6d59a53c5b399be998edada4b163edb673ca535 +c184b7bf1d3670cce100688f675f00d4f938d209c95cac55a32167d1d0b4a008 diff --git a/crates/event/src/contract/registry_v7.rs b/crates/event/src/contract/registry_v7.rs @@ -624,13 +624,6 @@ const TAG_CALENDAR_INCLUSION_REQUEST: TagContract = tag( TagValueType::AddressableCoordinate, true, ); -const TAG_E_ROOT: TagContract = tag( - "e", - TagCardinality::RequiredOne, - TagSemantic::RootEvent, - TagValueType::EventId, - true, -); const TAG_E_SOURCE_VERSION: TagContract = tag( "e", TagCardinality::RequiredOne, @@ -1128,13 +1121,6 @@ const TAG_CALENDAR_IMAGE: TagContract = tag( TagValueType::Url, false, ); -const TAG_SERVICE_OUTPUT: TagContract = tag( - "output", - TagCardinality::RequiredOne, - TagSemantic::ServiceOutput, - TagValueType::Text, - false, -); const TAG_URL: TagContract = tag( "url", TagCardinality::OptionalOne, @@ -1363,8 +1349,6 @@ const RHI_EVIDENCE_ATTESTATION_TAGS: &[TagContract] = &[ TAG_T_RHI_ATTESTATION_OUTCOME, TAG_E_RHI_SUPERSEDES_EVENT, ]; -const TRADE_VALIDATION_RECEIPT_TAGS: &[TagContract] = - &[TAG_E_ROOT, TAG_A_OPTIONAL, TAG_SERVICE_OUTPUT]; const KNOWLEDGE_SOURCE_TAGS: &[TagContract] = &[ TAG_D, TAG_CONTRACT_REQUIRED, @@ -2338,14 +2322,6 @@ static KIND_CONTRACTS_REGISTRY_V7: &[KindContract] = &[ ["radroots.trade.cancellation.v1"] ), kind_contract!( - KIND_TRADE_VALIDATION_RECEIPT, - "KIND_TRADE_VALIDATION_RECEIPT", - "Trade Validation Receipt", - EventClass::Regular, - NostrStandard::Radroots, - ["radroots.trade.validation_receipt.v1"] - ), - kind_contract!( KIND_RHI_EVIDENCE_ATTESTATION, "KIND_RHI_EVIDENCE_ATTESTATION", "RHI Evidence Attestation", @@ -3753,19 +3729,6 @@ static EVENT_CONTRACTS_REGISTRY_V7: &[EventContract] = &[ RHI_EVIDENCE_ATTESTATION_TAGS, TRADE_VALIDATION_REDUCERS ), - event_contract!( - "radroots.trade.validation_receipt.v1", - KIND_TRADE_VALIDATION_RECEIPT, - "Trade Validation Receipt", - "RadrootsTradeValidationReceipt", - EventClass::Regular, - EventPrivacy::Public, - AuthorRole::Service, - ContentSchema::JsonObject, - EventDiscriminator::KindOnly, - TRADE_VALIDATION_RECEIPT_TAGS, - TRADE_VALIDATION_REDUCERS - ), ]; pub fn all_kind_contracts() -> &'static [KindContract] { @@ -3864,8 +3827,7 @@ pub fn kind_contract_family(contract: &KindContract) -> Option<ContractFamily> { | KIND_FARM_WORKSPACE_MANIFEST | KIND_FARM_CRDT_CHANGE => ContractFamily::Farm, KIND_CLASSIFIED_LISTING => ContractFamily::Market, - KIND_TRADE_VALIDATION_RECEIPT - | KIND_RHI_EVIDENCE_ATTESTATION + KIND_RHI_EVIDENCE_ATTESTATION | KIND_TRADE_PROPOSAL | KIND_TRADE_DECISION | KIND_TRADE_REVISION_PROPOSAL diff --git a/crates/event/src/kinds.rs b/crates/event/src/kinds.rs @@ -88,7 +88,6 @@ pub const KIND_ORDER_REQUEST: u32 = 3422; pub const KIND_ORDER_DECISION: u32 = 3423; pub const KIND_ORDER_CANCELLATION: u32 = 3432; pub const KIND_TRADE_FORBIDDEN_3431: u32 = 3431; -pub const KIND_TRADE_VALIDATION_RECEIPT: u32 = 3440; pub const KIND_RHI_EVIDENCE_ATTESTATION: u32 = 3441; pub const KIND_KNOWLEDGE_CLAIM: u32 = 3460; pub const KIND_KNOWLEDGE_RELATION: u32 = 3461; @@ -175,16 +174,13 @@ pub const TRADE_MUTATION_EVENT_KINDS: [u32; 5] = [ KIND_TRADE_CANCELLATION, ]; -pub const TRADE_VALIDATION_EVENT_KINDS: [u32; 1] = [KIND_TRADE_VALIDATION_RECEIPT]; - -pub const COMMERCIAL_EVENT_KINDS: [u32; 7] = [ +pub const COMMERCIAL_EVENT_KINDS: [u32; 6] = [ KIND_CLASSIFIED_LISTING, KIND_TRADE_PROPOSAL, KIND_TRADE_DECISION, KIND_TRADE_REVISION_PROPOSAL, KIND_TRADE_REVISION_DECISION, KIND_TRADE_CANCELLATION, - KIND_TRADE_VALIDATION_RECEIPT, ]; pub const KIND_JOB_REQUEST_MIN: u32 = 5000; @@ -538,23 +534,6 @@ pub const fn is_private_farm_ops_kind(kind: u32) -> bool { } #[inline] -pub const fn is_trade_validation_service_request_kind(kind: u32) -> bool { - let _ = kind; - false -} - -#[inline] -pub const fn is_trade_validation_service_result_kind(kind: u32) -> bool { - let _ = kind; - false -} - -#[inline] -pub const fn is_trade_validation_service_event_kind(kind: u32) -> bool { - is_trade_validation_service_request_kind(kind) | is_trade_validation_service_result_kind(kind) -} - -#[inline] pub const fn is_order_event_kind(kind: u32) -> bool { matches!( kind, @@ -575,32 +554,8 @@ pub const fn is_trade_mutation_event_kind(kind: u32) -> bool { } #[inline] -pub const fn is_trade_validation_receipt_kind(kind: u32) -> bool { - kind == KIND_TRADE_VALIDATION_RECEIPT -} - -#[inline] -pub const fn is_trade_validation_event_kind(kind: u32) -> bool { - is_trade_validation_service_event_kind(kind) | is_trade_validation_receipt_kind(kind) -} - -#[inline] pub const fn is_commercial_event_kind(kind: u32) -> bool { - is_classified_listing_kind(kind) - || is_trade_mutation_event_kind(kind) - || is_trade_validation_event_kind(kind) -} - -#[inline] -pub const fn trade_validation_service_result_kind_for_request(kind: u32) -> Option<u32> { - let _ = kind; - None -} - -#[inline] -pub const fn trade_validation_service_request_kind_for_result(kind: u32) -> Option<u32> { - let _ = kind; - None + is_classified_listing_kind(kind) || is_trade_mutation_event_kind(kind) } #[inline] @@ -948,10 +903,6 @@ mod tests { ] ); assert_eq!( - TRADE_VALIDATION_EVENT_KINDS, - [KIND_TRADE_VALIDATION_RECEIPT] - ); - assert_eq!( COMMERCIAL_EVENT_KINDS, [ KIND_CLASSIFIED_LISTING, @@ -960,7 +911,6 @@ mod tests { KIND_TRADE_REVISION_PROPOSAL, KIND_TRADE_REVISION_DECISION, KIND_TRADE_CANCELLATION, - KIND_TRADE_VALIDATION_RECEIPT, ] ); @@ -976,7 +926,7 @@ mod tests { assert!(!is_order_event_kind(3434)); assert!(!is_order_event_kind(3435)); assert!(!is_order_event_kind(3436)); - assert!(!is_order_event_kind(KIND_TRADE_VALIDATION_RECEIPT)); + assert!(!is_order_event_kind(3440)); assert!(!is_order_event_kind(3431)); assert!(is_trade_mutation_event_kind(KIND_TRADE_PROPOSAL)); @@ -985,37 +935,15 @@ mod tests { assert!(is_trade_mutation_event_kind(KIND_TRADE_REVISION_DECISION)); assert!(is_trade_mutation_event_kind(KIND_TRADE_CANCELLATION)); assert!(!is_trade_mutation_event_kind(KIND_ORDER_REQUEST)); - assert!(!is_trade_mutation_event_kind(KIND_TRADE_VALIDATION_RECEIPT)); - - assert!(!is_trade_validation_service_request_kind(5321)); - assert!(!is_trade_validation_service_request_kind(5322)); - assert!(!is_trade_validation_service_result_kind(6321)); - assert!(!is_trade_validation_service_result_kind(6322)); - assert!(!is_trade_validation_service_event_kind(5321)); - assert!(!is_trade_validation_service_event_kind(6321)); - assert!(!is_trade_validation_service_event_kind(5322)); - assert!(!is_trade_validation_service_event_kind(6322)); - assert!(!is_trade_validation_service_event_kind(KIND_ORDER_REQUEST)); - assert!(is_trade_validation_receipt_kind( - KIND_TRADE_VALIDATION_RECEIPT - )); - assert!(!is_trade_validation_receipt_kind(3434)); - assert!(is_trade_validation_event_kind( - KIND_TRADE_VALIDATION_RECEIPT - )); - assert!(!is_trade_validation_event_kind(6322)); - assert!(!is_trade_validation_event_kind(3434)); + assert!(!is_trade_mutation_event_kind(3440)); assert!(is_commercial_event_kind(KIND_CLASSIFIED_LISTING)); assert!(is_commercial_event_kind(KIND_TRADE_PROPOSAL)); - assert!(is_commercial_event_kind(KIND_TRADE_VALIDATION_RECEIPT)); + assert!(!is_commercial_event_kind(3440)); assert!(!is_commercial_event_kind(KIND_ORDER_REQUEST)); assert!(!is_commercial_event_kind(KIND_PROFILE)); assert!(!is_commercial_event_kind(30403)); assert!(!is_commercial_event_kind(5321)); assert!(!is_commercial_event_kind(6321)); - - assert_eq!(trade_validation_service_result_kind_for_request(5321), None); - assert_eq!(trade_validation_service_request_kind_for_result(6321), None); } } diff --git a/crates/event/tests/source_boundary.rs b/crates/event/tests/source_boundary.rs @@ -43,6 +43,50 @@ const FORBIDDEN_EVENT_NAMES: &[ForbiddenEventName] = &[ pattern: "RadrootsSignedNostrEventParts", reason: "signed-event parts must use protocol-neutral domain names", }, + ForbiddenEventName { + pattern: "KIND_TRADE_VALIDATION_RECEIPT", + reason: "the prototype receipt kind is retired in favor of typed RHI attestations", + }, + ForbiddenEventName { + pattern: "TRADE_VALIDATION_EVENT_KINDS", + reason: "the prototype receipt family is retired", + }, + ForbiddenEventName { + pattern: concat!("is_trade_validation_", "receipt_kind"), + reason: "the prototype receipt classifier is retired", + }, + ForbiddenEventName { + pattern: "is_trade_validation_event_kind", + reason: "the prototype validation-event classifier is retired", + }, + ForbiddenEventName { + pattern: "is_trade_validation_service_event_kind", + reason: "the unused prototype service-event classifier is retired", + }, + ForbiddenEventName { + pattern: "is_trade_validation_service_request_kind", + reason: "the unused prototype service-request classifier is retired", + }, + ForbiddenEventName { + pattern: "is_trade_validation_service_result_kind", + reason: "the unused prototype service-result classifier is retired", + }, + ForbiddenEventName { + pattern: "trade_validation_service_result_kind_for_request", + reason: "the unused prototype service-kind mapper is retired", + }, + ForbiddenEventName { + pattern: "trade_validation_service_request_kind_for_result", + reason: "the unused prototype service-kind mapper is retired", + }, + ForbiddenEventName { + pattern: "RadrootsTradeValidationReceipt", + reason: "the prototype receipt DTO is retired in favor of the final evidence report", + }, + ForbiddenEventName { + pattern: "radroots.trade.validation_receipt.v1", + reason: "the prototype receipt contract is retired", + }, ]; const RETIRED_EVENT_MODULE_PATHS: &[&str] = &[ diff --git a/crates/event_bindings/src/model.rs b/crates/event_bindings/src/model.rs @@ -133,10 +133,6 @@ const EVENT_KIND_EXPORTS: &[(&str, u32)] = &[ kinds::KIND_TRADE_SELLER_RESERVATION_ASSERTION, ), ( - "KIND_TRADE_VALIDATION_RECEIPT", - kinds::KIND_TRADE_VALIDATION_RECEIPT, - ), - ( "KIND_RHI_EVIDENCE_ATTESTATION", kinds::KIND_RHI_EVIDENCE_ATTESTATION, ), diff --git a/crates/event_bindings/tests/fixtures/generated_kinds.ts b/crates/event_bindings/tests/fixtures/generated_kinds.ts @@ -120,8 +120,6 @@ export const KIND_TRADE_CANCELLATION = 3474; export const KIND_TRADE_SELLER_RESERVATION_ASSERTION = 3475; -export const KIND_TRADE_VALIDATION_RECEIPT = 3440; - export const KIND_RHI_EVIDENCE_ATTESTATION = 3441; export const KIND_KNOWLEDGE_CLAIM = 3460; diff --git a/crates/protocol/src/event/v1.rs b/crates/protocol/src/event/v1.rs @@ -80,12 +80,6 @@ pub const CATALOG: &[EventDescriptor] = &[ purpose: "authorized predecision cancellation", }, EventDescriptor { - name: "trade_validation_receipt", - kind: 3440, - event_class: EventClass::Regular, - purpose: "RHI validation result bound to root/target/listing/validator set", - }, - EventDescriptor { name: "dm_relay_list", kind: 10050, event_class: EventClass::Replaceable, @@ -119,7 +113,7 @@ pub const CATALOG: &[EventDescriptor] = &[ /// Event kinds rejected as retired V1 identities. pub const RETIRED_KINDS: &[u32] = &[ - 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3433, 3434, 5321, 5322, 6321, 6322, 30403, + 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3433, 3434, 3440, 5321, 5322, 6321, 6322, 30403, ]; // Private byte guards preserve fail-closed predecessor behavior without @@ -166,6 +160,10 @@ const RETIRED_NAME_BYTES: &[&[u8]] = &[ ], &[116, 114, 97, 100, 101, 95, 114, 101, 99, 101, 105, 112, 116], &[ + 116, 114, 97, 100, 101, 95, 118, 97, 108, 105, 100, 97, 116, 105, 111, 110, 95, 114, 101, + 99, 101, 105, 112, 116, + ], + &[ 116, 114, 97, 100, 101, 95, 116, 114, 97, 110, 115, 105, 116, 105, 111, 110, 95, 112, 114, 111, 111, 102, 95, 114, 101, 113, 117, 101, 115, 116, ], @@ -393,7 +391,7 @@ mod tests { #[test] fn event_catalog_retains_exact_v1_identifiers() { - assert_eq!(CATALOG.len(), 13); + assert_eq!(CATALOG.len(), 12); let listing = CATALOG .iter() .find(|event| event.kind == 30402) @@ -465,6 +463,16 @@ mod tests { kind: RETIRED_KINDS[0], }) ); + let retired_prototype = EventDescriptor { + name: "synthetic_prototype_name", + kind: 3440, + event_class: EventClass::Regular, + purpose: "retired", + }; + assert_eq!( + validate_catalog(&[retired_prototype]), + Err(Error::RetiredEventKind { kind: 3440 }) + ); const RETIRED_NAME: &str = concat!("listing", "_draft"); let retired_name = EventDescriptor { @@ -479,6 +487,19 @@ mod tests { name: RETIRED_NAME.into() }) ); + const RETIRED_PROTOTYPE_NAME: &str = concat!("trade_", "validation_receipt"); + let retired_prototype_name = EventDescriptor { + name: RETIRED_PROTOTYPE_NAME, + kind: u32::MAX, + event_class: EventClass::Regular, + purpose: "retired", + }; + assert_eq!( + validate_catalog(&[retired_prototype_name]), + Err(Error::RetiredEventName { + name: RETIRED_PROTOTYPE_NAME.into(), + }) + ); let duplicate_kind = EventDescriptor { name: "different_name", kind: first.kind, diff --git a/crates/protocol/tests/fixtures/protocol_v1.inventory.json b/crates/protocol/tests/fixtures/protocol_v1.inventory.json @@ -85,7 +85,7 @@ { "module": "event::v1", "path": "crates/protocol/src/event/v1.rs", - "sha256": "cc5b36e7e5cef0c7e375c2ce473267f5721994416d5154296a135890dface2e4", + "sha256": "9522617516b011e966cb7ee3c8f073b89fbd485e6c1776ad9ab65e563944daf3", "types": [ { "rust_path": "radroots_protocol::event::v1::EventClass", diff --git a/tools/xtask/src/contract.rs b/tools/xtask/src/contract.rs @@ -2582,18 +2582,12 @@ const TRADE_CANCELLATION_WITNESSES: [EventBoundarySourceWitness; 3] = [ }, ]; -const TRADE_VALIDATION_RECEIPT_WITNESSES: [EventBoundarySourceWitness; 1] = - [EventBoundarySourceWitness { - relative_path: "crates/event/src/kinds.rs", - required_fragments: &["pub const KIND_TRADE_VALIDATION_RECEIPT: u32 = 3440;"], - }]; - const RELAY_DOC_WITNESSES: [EventBoundarySourceWitness; 1] = [EventBoundarySourceWitness { relative_path: "crates/event/src/relay_document.rs", required_fragments: &["pub struct RelayDocument"], }]; -const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [ +const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 43] = [ EventBoundaryExpectation { domain: "profile", kind: "0", @@ -3031,17 +3025,6 @@ const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [ witnesses: &TRADE_CANCELLATION_WITNESSES, }, EventBoundaryExpectation { - domain: "trade:validation_receipt", - kind: "3440", - radroots_type: "RadrootsTradeValidationReceipt", - rpc_methods: &[ - "domains.trade.validation_receipt.get", - "domains.trade.validation_receipt.list", - "domains.trade.validation_receipt.verify", - ], - witnesses: &TRADE_VALIDATION_RECEIPT_WITNESSES, - }, - EventBoundaryExpectation { domain: "relay_doc", kind: "N/A", radroots_type: "RelayDocument", diff --git a/tools/xtask/src/generate/protocol.rs b/tools/xtask/src/generate/protocol.rs @@ -40,6 +40,7 @@ struct Config { source_hash_algorithm: String, inventory_path: String, inventory_sha256_path: String, + packaged_inventory_path: String, source: Vec<SourceConfig>, #[serde(default)] macro_generated_type: Vec<MacroGeneratedTypeConfig>, @@ -136,6 +137,8 @@ fn validate_config(config: &Config) -> Result<(), String> { } if config.inventory_path != "contracts/codegen/protocol_v1.inventory.json" || config.inventory_sha256_path != "contracts/codegen/protocol_v1.inventory.sha256" + || config.packaged_inventory_path + != "crates/protocol/tests/fixtures/protocol_v1.inventory.json" { return Err("protocol codegen output paths are fixed by contract".to_owned()); } @@ -262,6 +265,7 @@ fn render_outputs( .map_err(|error| format!("failed to serialize protocol DTO inventory: {error}"))?; inventory_bytes.push(b'\n'); let digest_bytes = format!("{}\n", sha256_hex(&inventory_bytes)).into_bytes(); + let packaged_inventory_bytes = inventory_bytes.clone(); Ok(vec![ GeneratedFile { @@ -284,6 +288,16 @@ fn render_outputs( display_path: config.inventory_sha256_path.clone(), bytes: digest_bytes, }, + GeneratedFile { + path: safe_workspace_file( + workspace_root, + &config.packaged_inventory_path, + true, + "packaged protocol DTO inventory output", + )?, + display_path: config.packaged_inventory_path.clone(), + bytes: packaged_inventory_bytes, + }, ]) } @@ -569,6 +583,7 @@ struct PrivateWire; let root = workspace.path(); fs::create_dir_all(root.join("src")).expect("source directory"); fs::create_dir_all(root.join("out")).expect("output directory"); + fs::create_dir_all(root.join("packaged")).expect("packaged output directory"); fs::write( root.join("src/types.rs"), "#[derive(serde::Serialize)] pub struct Demo { pub value: String }\n", @@ -580,6 +595,7 @@ struct PrivateWire; source_hash_algorithm: HASH_ALGORITHM.to_owned(), inventory_path: "out/inventory.json".to_owned(), inventory_sha256_path: "out/inventory.sha256".to_owned(), + packaged_inventory_path: "packaged/inventory.json".to_owned(), source: vec![SourceConfig { module: "demo::v1".to_owned(), path: "src/types.rs".to_owned(), @@ -595,11 +611,17 @@ struct PrivateWire; let second = render_outputs(root, &config, schemas).expect("second render"); assert_eq!(first[0].bytes, second[0].bytes); assert_eq!(first[1].bytes, second[1].bytes); + assert_eq!(first[2].bytes, second[2].bytes); + assert_eq!(first[0].bytes, first[2].bytes); write_outputs(&first).expect("write"); check_outputs(&second).expect("fresh"); fs::write(root.join("out/inventory.json"), "stale\n").expect("drift"); let error = check_outputs(&second).expect_err("reject drift"); assert!(error.contains("stale `out/inventory.json`")); + write_outputs(&second).expect("restore outputs"); + fs::write(root.join("packaged/inventory.json"), "stale\n").expect("packaged drift"); + let error = check_outputs(&second).expect_err("reject packaged drift"); + assert!(error.contains("stale `packaged/inventory.json`")); } #[test]