lib

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

source_boundary.rs (38623B)


      1 use std::{
      2     fs,
      3     path::{Path, PathBuf},
      4 };
      5 
      6 struct ForbiddenConcept {
      7     pattern: &'static str,
      8     reason: &'static str,
      9 }
     10 
     11 const TRANSPORT_HARDENING_CRATE_SOURCE_ROOTS: &[&str] = &[
     12     "protocol/src/radrootsd/transport_publish",
     13     "transport/src",
     14     "transport_reticulum/src",
     15     "transport_nostr/src",
     16 ];
     17 
     18 const GENERIC_TRANSPORT_STATUS_SOURCE_ROOTS: &[&str] = &[
     19     "mesh_agent_proto/src",
     20     "protocol/src/radrootsd/transport_publish",
     21     "transport/src",
     22     "transport_reticulum/src",
     23 ];
     24 
     25 const CORE_STATUS_CONTRACT_SOURCE_ROOTS: &[&str] = &["transport/src", "transport_reticulum/src"];
     26 
     27 const CORE_TRANSPORT_CONTRACT_SOURCE_ROOTS: &[&str] = &["transport/src"];
     28 
     29 const TRANSPORT_CONSUMER_SOURCE_ROOTS: &[&str] = &[
     30     "mesh/src",
     31     "mesh_agent_client/src",
     32     "protocol/src/radrootsd/transport_publish",
     33     "transport_nostr/src",
     34     "transport_reticulum/src",
     35 ];
     36 
     37 const RETIRED_TRANSPORT_TYPE_NAMES: &[&str] = &[
     38     "RadrootsTransportKind",
     39     "RadrootsTransportMeshScopeId",
     40     "RadrootsTransportTarget",
     41     "RadrootsTransportTargetFingerprint",
     42     "RadrootsTransportTargetLabel",
     43     "RadrootsTransportTargetSet",
     44 ];
     45 
     46 const DELIVERY_PAYLOAD_CONTRACT_SOURCE_ROOTS: &[&str] =
     47     &["transport/src", "transport_reticulum/src", "sync/src"];
     48 
     49 const FOUNDATION_HARDENING_DOC_ROOTS: &[&str] = &["contracts", "docs"];
     50 
     51 const FORBIDDEN_TRANSPORT_CONCEPTS: &[ForbiddenConcept] = &[
     52     ForbiddenConcept {
     53         pattern: concat!("\"radrootsd", "_", "pro", "xy\""),
     54         reason: "radrootsd execution must not be modeled as transport identity",
     55     },
     56     ForbiddenConcept {
     57         pattern: concat!("radrootsd.publish", "_", "pro", "xy.v1"),
     58         reason: "transport publish protocol v1 radrootsd execution identifiers are removed",
     59     },
     60     ForbiddenConcept {
     61         pattern: "publish.relays.resolve",
     62         reason: "relay-resolution RPC is replaced by transport publish target policy",
     63     },
     64     ForbiddenConcept {
     65         pattern: "\"publish.event\"",
     66         reason: "publish.event is replaced by transport.publish.event",
     67     },
     68     ForbiddenConcept {
     69         pattern: "transport_kinds",
     70         reason: "capabilities must expose per-transport readiness instead of kind-only lists",
     71     },
     72     ForbiddenConcept {
     73         pattern: "allowed_relay_policy",
     74         reason: "relay policy is Nostr-specific and must not be a generic transport API",
     75     },
     76     ForbiddenConcept {
     77         pattern: "relay_policy",
     78         reason: "relay policy is Nostr-specific and must not be a generic transport API",
     79     },
     80     ForbiddenConcept {
     81         pattern: "PublishRelayPolicy",
     82         reason: "old relay-shaped publish policy names must not return",
     83     },
     84     ForbiddenConcept {
     85         pattern: "PublishRelayOutcome",
     86         reason: "old relay-shaped publish outcome names must not return",
     87     },
     88     ForbiddenConcept {
     89         pattern: "PublishRelaySource",
     90         reason: "old relay-shaped publish source names must not return",
     91     },
     92     ForbiddenConcept {
     93         pattern: concat!("Nostr", "Fetch"),
     94         reason: "generic transport observations must use transport-neutral fetch naming",
     95     },
     96     ForbiddenConcept {
     97         pattern: concat!("Nostr", "Subscription"),
     98         reason: "generic transport observations must use transport-neutral subscription naming",
     99     },
    100     ForbiddenConcept {
    101         pattern: concat!("Nostr", "PublishAck"),
    102         reason: "generic transport observations must use transport-neutral publish ack naming",
    103     },
    104     ForbiddenConcept {
    105         pattern: concat!("nostr", "_fetch"),
    106         reason: "generic transport observation storage strings must be transport-neutral",
    107     },
    108     ForbiddenConcept {
    109         pattern: concat!("nostr", "_subscription"),
    110         reason: "generic transport observation storage strings must be transport-neutral",
    111     },
    112     ForbiddenConcept {
    113         pattern: concat!("nostr", "_publish_ack"),
    114         reason: "generic transport observation storage strings must be transport-neutral",
    115     },
    116 ];
    117 
    118 const FORBIDDEN_CORE_STATUS_CONCEPTS: &[ForbiddenConcept] = &[
    119     ForbiddenConcept {
    120         pattern: "implementation_state",
    121         reason: "public transport status must use implementation",
    122     },
    123     ForbiddenConcept {
    124         pattern: "readiness",
    125         reason: "public transport status must use configured, usable_for_delivery, and message",
    126     },
    127     ForbiddenConcept {
    128         pattern: "publish_usable",
    129         reason: "public transport status must use usable_for_delivery",
    130     },
    131     ForbiddenConcept {
    132         pattern: "fetch_usable",
    133         reason: "public transport status must use usable_for_delivery",
    134     },
    135     ForbiddenConcept {
    136         pattern: "redacted_message",
    137         reason: "public transport status must use message",
    138     },
    139     ForbiddenConcept {
    140         pattern: "RadrootsTransportReadinessState",
    141         reason: "readiness state is no longer a public transport status contract",
    142     },
    143     ForbiddenConcept {
    144         pattern: "Misconfigured",
    145         reason: "configuration is modeled by configured and message",
    146     },
    147     ForbiddenConcept {
    148         pattern: "Disabled",
    149         reason: "disabled state is modeled by configured, usable_for_delivery, and message",
    150     },
    151 ];
    152 
    153 const FORBIDDEN_GENERIC_TRANSPORT_STATUS_CONCEPTS: &[ForbiddenConcept] = &[
    154     ForbiddenConcept {
    155         pattern: concat!("configured_nostr", "_relay", "_count"),
    156         reason: "generic status surfaces must expose configured transport target counts",
    157     },
    158     ForbiddenConcept {
    159         pattern: concat!("configured_nostr", "_relays"),
    160         reason: "generic status surfaces must expose configured transport targets",
    161     },
    162     ForbiddenConcept {
    163         pattern: concat!("target", "_relays"),
    164         reason: "generic transport target surfaces must use endpoint terminology",
    165     },
    166     ForbiddenConcept {
    167         pattern: concat!("connected", "_relays"),
    168         reason: "generic transport attempt surfaces must use endpoint terminology",
    169     },
    170     ForbiddenConcept {
    171         pattern: concat!("acknowledged", "_relays"),
    172         reason: "generic transport acknowledgement surfaces must use endpoint terminology",
    173     },
    174     ForbiddenConcept {
    175         pattern: concat!("failed", "_relays"),
    176         reason: "generic transport failure surfaces must use target terminology",
    177     },
    178     ForbiddenConcept {
    179         pattern: concat!("relay", "_count"),
    180         reason: "generic transport status counts must use transport target terminology",
    181     },
    182 ];
    183 
    184 const FORBIDDEN_CORE_TRANSPORT_CONCEPTS: &[ForbiddenConcept] = &[
    185     ForbiddenConcept {
    186         pattern: concat!("Radroots", "Relay"),
    187         reason: "core transport contracts must not expose Nostr relay-shaped APIs",
    188     },
    189     ForbiddenConcept {
    190         pattern: concat!("Relay", "Transport"),
    191         reason: "core transport contracts must use transport-neutral names",
    192     },
    193     ForbiddenConcept {
    194         pattern: concat!("relay", "_transport"),
    195         reason: "core transport contracts must use transport-neutral names",
    196     },
    197 ];
    198 
    199 const FORBIDDEN_DELIVERY_PAYLOAD_CONCEPTS: &[ForbiddenConcept] = &[
    200     ForbiddenConcept {
    201         pattern: "payload_digest",
    202         reason: "delivery requests must carry DeliveryPayload instead of digest-only fields",
    203     },
    204     ForbiddenConcept {
    205         pattern: "DigestOnly",
    206         reason: "runtime dispatch must not retain a digest-only payload path",
    207     },
    208     ForbiddenConcept {
    209         pattern: "RadrootsTransportPayload::signed_event_json(",
    210         reason: "signed-event payload construction must name unchecked validation explicitly",
    211     },
    212     ForbiddenConcept {
    213         pattern: "RadrootsTransportPayload::signed_event_json_with_digest(",
    214         reason: "signed-event digest validation must name unchecked validation explicitly",
    215     },
    216 ];
    217 
    218 const FORBIDDEN_FOUNDATION_HARDENING_RETIRED_CONCEPTS: &[ForbiddenConcept] = &[
    219     ForbiddenConcept {
    220         pattern: "SignedNostrEvent",
    221         reason: "generic signed-event surfaces must use product-neutral signed-event names",
    222     },
    223     ForbiddenConcept {
    224         pattern: "RadrootsEventIndexIndexCheckpoint",
    225         reason: "event-index checkpoint names must not duplicate the index noun",
    226     },
    227     ForbiddenConcept {
    228         pattern: "RadrootsEventsIndexed",
    229         reason: "event-indexed APIs must use the singular event-index crate family",
    230     },
    231     ForbiddenConcept {
    232         pattern: "RADROOTS_EVENTS_VERSION",
    233         reason: "event contract version constants must use the current singular event namespace",
    234     },
    235     ForbiddenConcept {
    236         pattern: "radroots_events",
    237         reason: "crate and manifest surfaces must use the current singular event crate names",
    238     },
    239     ForbiddenConcept {
    240         pattern: "radroots_events_codec",
    241         reason: "event codec crate surfaces must use the current singular event-codec name",
    242     },
    243     ForbiddenConcept {
    244         pattern: "radroots_events_indexed",
    245         reason: "event index crate surfaces must use the current singular event-index name",
    246     },
    247     ForbiddenConcept {
    248         pattern: "radroots_local_events",
    249         reason: "local event storage must not reintroduce retired local-events crate names",
    250     },
    251     ForbiddenConcept {
    252         pattern: "radroots_local_store",
    253         reason: "runtime storage must not reintroduce retired local-store crate names",
    254     },
    255     ForbiddenConcept {
    256         pattern: "radroots_types",
    257         reason: "shared type surfaces must use current crate ownership instead of retired types crates",
    258     },
    259     ForbiddenConcept {
    260         pattern: "radroots_types_bindings",
    261         reason: "generated bindings must not reintroduce retired types-binding crate names",
    262     },
    263     ForbiddenConcept {
    264         pattern: "radroots_nostr_ndb",
    265         reason: "Nostr database ownership must not reintroduce retired ndb crate names",
    266     },
    267     ForbiddenConcept {
    268         pattern: "radroots_replica_db",
    269         reason: "replica database surfaces must use current replica-store ownership",
    270     },
    271     ForbiddenConcept {
    272         pattern: "radroots_replica_db_schema",
    273         reason: "replica schema surfaces must use current replica-schema ownership",
    274     },
    275     ForbiddenConcept {
    276         pattern: "radroots_sp1_guest_trade",
    277         reason: "trade SP1 crate surfaces must use the current trade_sp1 crate names",
    278     },
    279     ForbiddenConcept {
    280         pattern: "radroots_sp1_host_trade",
    281         reason: "trade SP1 crate surfaces must use the current trade_sp1 crate names",
    282     },
    283 ];
    284 
    285 const FORBIDDEN_FOUNDATION_HARDENING_DOC_CONCEPTS: &[ForbiddenConcept] = &[
    286     ForbiddenConcept {
    287         pattern: "Nostr event timestamp",
    288         reason: "generic docs must describe event-envelope timestamps without protocol leakage",
    289     },
    290     ForbiddenConcept {
    291         pattern: "Forwarded satisfies Delivered",
    292         reason: "forwarded evidence must not be documented as strict delivery",
    293     },
    294     ForbiddenConcept {
    295         pattern: "StoredByGateway satisfies Delivered",
    296         reason: "gateway storage evidence must not be documented as strict delivery",
    297     },
    298     ForbiddenConcept {
    299         pattern: "Seen satisfies Delivered",
    300         reason: "seen evidence must not be documented as strict delivery",
    301     },
    302 ];
    303 
    304 #[test]
    305 fn transport_hardening_sources_reject_removed_protocol_identifiers() {
    306     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    307         .parent()
    308         .expect("transport crate parent");
    309     let mut findings = Vec::new();
    310 
    311     for relative_root in TRANSPORT_HARDENING_CRATE_SOURCE_ROOTS {
    312         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    313             let source_raw = read_source(path.as_path());
    314             let source = production_source(source_raw.as_str());
    315             let relative_path = relative_path(crates_root, path.as_path());
    316 
    317             for concept in FORBIDDEN_TRANSPORT_CONCEPTS {
    318                 if contains_forbidden_concept(source, concept.pattern) {
    319                     findings.push(format!(
    320                         "{} contains removed transport concept `{}`: {}",
    321                         relative_path, concept.pattern, concept.reason
    322                     ));
    323                 }
    324             }
    325 
    326             for line in removed_reticulum_stage_endpoint_lines(source) {
    327                 findings.push(format!(
    328                     "{relative_path}:{line} contains removed Reticulum staging endpoint"
    329                 ));
    330             }
    331         }
    332     }
    333 
    334     assert!(
    335         findings.is_empty(),
    336         "transport hardening source-boundary violations:\n{}",
    337         findings.join("\n")
    338     );
    339 }
    340 
    341 #[test]
    342 fn core_status_contract_sources_reject_retired_public_status_fields() {
    343     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    344         .parent()
    345         .expect("transport crate parent");
    346     let mut findings = Vec::new();
    347 
    348     for relative_root in CORE_STATUS_CONTRACT_SOURCE_ROOTS {
    349         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    350             let source_raw = read_source(path.as_path());
    351             let source = production_source(source_raw.as_str());
    352             let relative_path = relative_path(crates_root, path.as_path());
    353 
    354             for concept in FORBIDDEN_CORE_STATUS_CONCEPTS {
    355                 if contains_forbidden_concept(source, concept.pattern) {
    356                     findings.push(format!(
    357                         "{} contains retired core transport status concept `{}`: {}",
    358                         relative_path, concept.pattern, concept.reason
    359                     ));
    360                 }
    361             }
    362         }
    363     }
    364 
    365     assert!(
    366         findings.is_empty(),
    367         "core transport status source-boundary violations:\n{}",
    368         findings.join("\n")
    369     );
    370 }
    371 
    372 #[test]
    373 fn generic_transport_status_sources_reject_retired_relay_shaped_names() {
    374     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    375         .parent()
    376         .expect("transport crate parent");
    377     let mut findings = Vec::new();
    378 
    379     for relative_root in GENERIC_TRANSPORT_STATUS_SOURCE_ROOTS {
    380         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    381             let source_raw = read_source(path.as_path());
    382             let source = production_source(source_raw.as_str());
    383             let relative_path = relative_path(crates_root, path.as_path());
    384 
    385             for concept in FORBIDDEN_GENERIC_TRANSPORT_STATUS_CONCEPTS {
    386                 if contains_forbidden_concept(source, concept.pattern) {
    387                     findings.push(format!(
    388                         "{} contains retired generic transport status concept `{}`: {}",
    389                         relative_path, concept.pattern, concept.reason
    390                     ));
    391                 }
    392             }
    393         }
    394     }
    395 
    396     assert!(
    397         findings.is_empty(),
    398         "generic transport status source-boundary violations:\n{}",
    399         findings.join("\n")
    400     );
    401 }
    402 
    403 #[test]
    404 fn core_transport_sources_reject_relay_shaped_public_contracts() {
    405     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    406         .parent()
    407         .expect("transport crate parent");
    408     let mut findings = Vec::new();
    409 
    410     for relative_root in CORE_TRANSPORT_CONTRACT_SOURCE_ROOTS {
    411         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    412             let source_raw = read_source(path.as_path());
    413             let source = production_source(source_raw.as_str());
    414             let relative_path = relative_path(crates_root, path.as_path());
    415 
    416             for concept in FORBIDDEN_CORE_TRANSPORT_CONCEPTS {
    417                 if contains_forbidden_concept(source, concept.pattern) {
    418                     findings.push(format!(
    419                         "{} contains relay-shaped core transport concept `{}`: {}",
    420                         relative_path, concept.pattern, concept.reason
    421                     ));
    422                 }
    423             }
    424         }
    425     }
    426 
    427     assert!(
    428         findings.is_empty(),
    429         "core transport public contract source-boundary violations:\n{}",
    430         findings.join("\n")
    431     );
    432 }
    433 
    434 #[test]
    435 fn delivery_request_sources_require_payload_objects() {
    436     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    437         .parent()
    438         .expect("transport crate parent");
    439     let mut findings = Vec::new();
    440 
    441     for relative_root in DELIVERY_PAYLOAD_CONTRACT_SOURCE_ROOTS {
    442         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    443             let source_raw = read_source(path.as_path());
    444             let source = production_source(source_raw.as_str());
    445             let relative_path = relative_path(crates_root, path.as_path());
    446 
    447             for concept in FORBIDDEN_DELIVERY_PAYLOAD_CONCEPTS {
    448                 if contains_forbidden_concept(source, concept.pattern) {
    449                     findings.push(format!(
    450                         "{} contains digest-only delivery concept `{}`: {}",
    451                         relative_path, concept.pattern, concept.reason
    452                     ));
    453                 }
    454             }
    455         }
    456     }
    457 
    458     assert!(
    459         findings.is_empty(),
    460         "delivery payload source-boundary violations:\n{}",
    461         findings.join("\n")
    462     );
    463 }
    464 
    465 #[test]
    466 fn foundation_hardening_repo_sources_reject_retired_names_and_ambiguous_docs() {
    467     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    468         .parent()
    469         .expect("transport crate parent");
    470     let repo_root = crates_root.parent().expect("repo root");
    471     let mut findings = Vec::new();
    472 
    473     for path in foundation_hardening_guard_files(repo_root) {
    474         let source = read_source(path.as_path());
    475         let relative_path = relative_path(repo_root, path.as_path());
    476 
    477         for concept in FORBIDDEN_FOUNDATION_HARDENING_RETIRED_CONCEPTS {
    478             if contains_forbidden_concept(source.as_str(), concept.pattern) {
    479                 findings.push(format!(
    480                     "{} contains retired Foundation Hardening concept `{}`: {}",
    481                     relative_path, concept.pattern, concept.reason
    482                 ));
    483             }
    484         }
    485 
    486         if is_doc_surface(path.as_path()) {
    487             for concept in FORBIDDEN_FOUNDATION_HARDENING_DOC_CONCEPTS {
    488                 if source.contains(concept.pattern) {
    489                     findings.push(format!(
    490                         "{} contains ambiguous Foundation Hardening wording `{}`: {}",
    491                         relative_path, concept.pattern, concept.reason
    492                     ));
    493                 }
    494             }
    495         }
    496     }
    497 
    498     assert!(
    499         findings.is_empty(),
    500         "Foundation Hardening V1 source-boundary violations:\n{}",
    501         findings.join("\n")
    502     );
    503 }
    504 
    505 #[test]
    506 fn workspace_consumers_use_only_the_final_split_transport_spis() {
    507     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    508         .parent()
    509         .expect("transport crate parent");
    510     assert!(
    511         !crates_root.join("runtime").exists(),
    512         "the predecessor runtime package must remain retired"
    513     );
    514     let reticulum_source_raw =
    515         read_source(crates_root.join("transport_reticulum/src/lib.rs").as_path());
    516     let reticulum_source = production_source(reticulum_source_raw.as_str());
    517     for required in [
    518         "impl EventSource for RadrootsReticulumTransport",
    519         "impl EventSink for RadrootsReticulumTransport",
    520     ] {
    521         assert!(
    522             reticulum_source.contains(required),
    523             "Reticulum preview must implement final split SPI witness `{required}`"
    524         );
    525     }
    526     assert!(!reticulum_source.contains("RadrootsRuntimeTransportShim"));
    527 
    528     let nostr_sink = read_source(crates_root.join("transport_nostr/src/sink.rs").as_path());
    529     let nostr_source = read_source(crates_root.join("transport_nostr/src/source.rs").as_path());
    530     assert!(
    531         nostr_sink.contains("impl EventSink for NostrTransport"),
    532         "Nostr adapter must implement the final sink SPI"
    533     );
    534     assert!(
    535         nostr_source.contains("impl EventSource for NostrTransport"),
    536         "Nostr adapter must implement the final source SPI"
    537     );
    538     assert!(
    539         !nostr_sink.contains("RadrootsRuntimeTransportShim")
    540             && !nostr_source.contains("RadrootsRuntimeTransportShim"),
    541         "Nostr adapter must not implement the predecessor monolithic SPI"
    542     );
    543 }
    544 
    545 #[test]
    546 fn canonical_workspace_consumers_reject_retired_transport_type_names() {
    547     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    548         .parent()
    549         .expect("transport crate parent");
    550     let mut findings = Vec::new();
    551 
    552     for relative_root in TRANSPORT_CONSUMER_SOURCE_ROOTS {
    553         for path in rust_source_files(crates_root.join(relative_root).as_path()) {
    554             if path
    555                 .components()
    556                 .any(|component| component.as_os_str() == "generated")
    557             {
    558                 continue;
    559             }
    560             let source_raw = read_source(path.as_path());
    561             let source = production_source(source_raw.as_str());
    562             let relative_path = relative_path(crates_root, path.as_path());
    563             for retired in RETIRED_TRANSPORT_TYPE_NAMES {
    564                 if contains_forbidden_concept(source, retired) {
    565                     findings.push(format!(
    566                         "{relative_path} still consumes retired transport type `{retired}`"
    567                     ));
    568                 }
    569             }
    570         }
    571     }
    572 
    573     assert!(
    574         findings.is_empty(),
    575         "canonical transport consumer migration violations:\n{}",
    576         findings.join("\n")
    577     );
    578 }
    579 
    580 #[test]
    581 fn transport_publish_capabilities_keep_canonical_status_fields() {
    582     let source_raw = read_source(
    583         Path::new(env!("CARGO_MANIFEST_DIR"))
    584             .parent()
    585             .expect("transport crate parent")
    586             .join("protocol/src/radrootsd/transport_publish/v5.rs")
    587             .as_path(),
    588     );
    589     let source = production_source(source_raw.as_str());
    590 
    591     for required in [
    592         "pub transport: String,",
    593         "pub configured: bool,",
    594         "pub implementation: Implementation,",
    595         "pub maturity: CapabilityMaturity,",
    596         "pub availability: CapabilityAvailability,",
    597         "pub usable_for_delivery: bool,",
    598         "pub capabilities: OperationCapabilities,",
    599         "pub struct OperationCapabilities",
    600         "pub deliver: bool,",
    601         "pub fetch: bool,",
    602         "pub discovery: bool,",
    603         "pub gateway_forwarding: bool,",
    604         "pub receipt_observation: bool,",
    605         "Implementation::Real",
    606         "CapabilityMaturity::Preview",
    607         "CapabilityAvailability::Unavailable",
    608         "configured: true",
    609         "usable_for_delivery: true",
    610         "usable_for_delivery: false",
    611         "capabilities: OperationCapabilities",
    612         "deliver: true",
    613         "fetch: false",
    614         "discovery: false",
    615         "gateway_forwarding: false",
    616         "receipt_observation: false",
    617     ] {
    618         assert!(
    619             source.contains(required),
    620             "transport publish capabilities must retain canonical status field `{required}`"
    621         );
    622     }
    623 
    624     for forbidden in [
    625         "pub implementation_state: TransportPublishImplementationState,",
    626         "TransportPublishImplementationState",
    627     ] {
    628         assert!(
    629             !source.contains(forbidden),
    630             "transport publish capabilities must not retain retired status field `{forbidden}`"
    631         );
    632     }
    633 }
    634 
    635 #[test]
    636 fn transport_target_identity_sources_reject_silent_dedupe() {
    637     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    638         .parent()
    639         .expect("transport crate parent");
    640 
    641     let transport_source = read_source(crates_root.join("transport/src/target.rs").as_path());
    642     for required in [
    643         "let mut fingerprints = BTreeSet::new();",
    644         "TransportError::DuplicateTargetFingerprint",
    645         "targets.len() > TARGET_SET_MAX_ITEMS",
    646     ] {
    647         assert!(
    648             transport_source.contains(required),
    649             "transport target set source must retain duplicate rejection witness `{required}`"
    650         );
    651     }
    652     let target_struct = source_between(
    653         transport_source.as_str(),
    654         "pub struct Target {",
    655         "impl Target {",
    656     );
    657     for forbidden in [
    658         "pub kind:",
    659         "pub uri:",
    660         "pub scope:",
    661         "pub label:",
    662         "pub fingerprint:",
    663     ] {
    664         assert!(
    665             !target_struct.contains(forbidden),
    666             "transport target identity field must remain sealed: `{forbidden}`"
    667         );
    668     }
    669     for required in [
    670         "impl<'de> serde::Deserialize<'de> for Target",
    671         "impl<'de> serde::Deserialize<'de> for TargetSet",
    672     ] {
    673         assert!(
    674             transport_source.contains(required),
    675             "transport target source must retain checked deserialization witness `{required}`"
    676         );
    677     }
    678 
    679     let reticulum_source = read_source(
    680         crates_root
    681             .join("transport_reticulum/src/contract.rs")
    682             .as_path(),
    683     );
    684     let destination_struct = source_between(
    685         reticulum_source.as_str(),
    686         "pub struct ReticulumDestinationV1 {",
    687         "impl ReticulumDestinationV1 {",
    688     );
    689     for forbidden in ["pub uri:", "pub routing:", "pub label:", "pub fingerprint:"] {
    690         assert!(
    691             !destination_struct.contains(forbidden),
    692             "Reticulum destination identity field must remain sealed: `{forbidden}`"
    693         );
    694     }
    695     assert!(
    696         reticulum_source.contains("impl<'de> serde::Deserialize<'de> for ReticulumDestinationV1"),
    697         "Reticulum destination source must retain checked deserialization"
    698     );
    699 
    700     let relay_source = read_source(crates_root.join("transport_nostr/src/relay.rs").as_path());
    701     let profile_source = read_source(crates_root.join("transport_nostr/src/profile.rs").as_path());
    702     for required in ["Target::nostr_relay(original)", "Error::DuplicateRelayUrl"] {
    703         let source = if required.contains("Duplicate") {
    704             profile_source.as_str()
    705         } else {
    706             relay_source.as_str()
    707         };
    708         assert!(
    709             source.contains(required),
    710             "Nostr relay target source must retain canonical identity witness `{required}`"
    711         );
    712     }
    713     for forbidden in [
    714         "impl<'de> Deserialize<'de> for RelayUrl",
    715         "impl<'de> Deserialize<'de> for RadrootsRelayTargetSet",
    716     ] {
    717         assert!(
    718             !relay_source.contains(forbidden),
    719             "policy-free Nostr relay identity must not regain deserialization: `{forbidden}`"
    720         );
    721     }
    722 
    723     let protocol_source = read_source(
    724         crates_root
    725             .join("protocol/src/radrootsd/transport_publish/v5.rs")
    726             .as_path(),
    727     );
    728     for required in [
    729         "target.validate_structure(index)?;",
    730         "return Err(Error::DuplicateTarget { index });",
    731         "Err(Error::DuplicateTarget { index: 1 })",
    732     ] {
    733         assert!(
    734             protocol_source.contains(required),
    735             "transport publish protocol must retain explicit-target duplicate rejection witness `{required}`"
    736         );
    737     }
    738 
    739     assert!(
    740         !crates_root.join("outbox").exists(),
    741         "the predecessor outbox package must remain retired"
    742     );
    743 }
    744 
    745 #[test]
    746 fn required_target_semantics_stay_fingerprint_exact() {
    747     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    748         .parent()
    749         .expect("transport crate parent");
    750 
    751     let protocol_source = read_source(
    752         crates_root
    753             .join("protocol/src/radrootsd/transport_publish/v5.rs")
    754             .as_path(),
    755     );
    756     for required in [
    757         "Self::RequiredTargets { targets } => targets.len()",
    758         "validate_required_target_fingerprints(targets.as_slice())",
    759         "Error::DuplicateRequiredTargetFingerprint { index }",
    760         "Matching fingerprints to native targets is intentionally deferred",
    761     ] {
    762         assert!(
    763             protocol_source.contains(required),
    764             "transport publish protocol must retain exact required-target witness `{required}`"
    765         );
    766     }
    767 
    768     let nostr_publish_source =
    769         read_source(crates_root.join("transport_nostr/src/sink.rs").as_path());
    770     for required in [
    771         "DeliveryReceipt::for_request(&request, receipts)",
    772         "DeliveryTargetReceipt::attempted(target, outcome)",
    773         "DeliveryTargetReceipt::skipped(",
    774     ] {
    775         assert!(
    776             nostr_publish_source.contains(required),
    777             "Nostr sink must delegate exact target satisfaction to the generic receipt contract `{required}`"
    778         );
    779     }
    780     assert!(!crates_root.join("transport_nostr/src/outbox.rs").exists());
    781     assert!(!crates_root.join("transport_nostr/src/publish.rs").exists());
    782 }
    783 
    784 #[test]
    785 fn transport_identity_is_extensible_and_reticulum_contracts_are_preview_owned() {
    786     let crates_root = Path::new(env!("CARGO_MANIFEST_DIR"))
    787         .parent()
    788         .expect("transport crate parent");
    789     let transport_id = read_source(crates_root.join("transport/src/id.rs").as_path());
    790     for required in [
    791         "pub struct TransportId(",
    792         "pub const LOCAL:",
    793         "pub const NOSTR:",
    794         "pub const RETICULUM:",
    795         "pub const RADROOTSD:",
    796         "ProtocolTransportKind::parse",
    797     ] {
    798         assert!(
    799             transport_id.contains(required),
    800             "transport identity source must retain extensible identity witness `{required}`"
    801         );
    802     }
    803     assert!(!transport_id.contains("pub enum TransportId"));
    804 
    805     let protocol_identity =
    806         read_source(crates_root.join("protocol/src/capability/v1.rs").as_path());
    807     assert!(protocol_identity.contains("pub struct TransportKind"));
    808     assert!(!protocol_identity.contains("pub enum TransportKind"));
    809     assert!(protocol_identity.contains("MAX_TRANSPORT_KIND_BYTES"));
    810 
    811     let transport_root_source = read_source(crates_root.join("transport/src/lib.rs").as_path());
    812     for forbidden in [
    813         "RADROOTS_RETICULUM_ENDPOINT_URI",
    814         "RADROOTS_RETICULUM_SCOPE_ID",
    815         "RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE",
    816         "ReticulumCapabilityReportV1",
    817         "ReticulumDestinationV1",
    818         "ReticulumFragmentPolicyV1",
    819         "ReticulumPayloadPolicyV1",
    820         "ReticulumRoutingMetadataV1",
    821     ] {
    822         assert!(
    823             !transport_root_source.contains(forbidden),
    824             "generic transport root must not expose Reticulum-specific symbol `{forbidden}`"
    825         );
    826     }
    827     assert!(
    828         !crates_root.join("transport/src/message.rs").exists(),
    829         "generic transport must not retain the Reticulum message module"
    830     );
    831     assert!(
    832         !crates_root.join("transport/src/reticulum.rs").exists(),
    833         "generic transport must not retain the Reticulum contract module"
    834     );
    835 
    836     let reticulum_message_source = read_source(
    837         crates_root
    838             .join("transport_reticulum/src/message.rs")
    839             .as_path(),
    840     );
    841     for required in [
    842         "RADROOTS_RETICULUM_ENDPOINT_URI",
    843         "reticulum:local",
    844         "RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE",
    845         "Reticulum transport is configured, ",
    846         "but this build does not implement Reticulum delivery.",
    847     ] {
    848         assert!(
    849             reticulum_message_source.contains(required),
    850             "private Reticulum message source must retain contract witness `{required}`"
    851         );
    852     }
    853     for forbidden in [
    854         "Reticulum prerelease transport is registered, ",
    855         "future compatibility",
    856         "compatibility mode",
    857         "fallback behavior",
    858         "hidden transport substitution",
    859     ] {
    860         assert!(
    861             !reticulum_message_source.contains(forbidden),
    862             "private Reticulum message source must not retain superseded copy `{forbidden}`"
    863         );
    864     }
    865 
    866     let reticulum_source =
    867         read_source(crates_root.join("transport_reticulum/src/lib.rs").as_path());
    868     assert!(
    869         reticulum_source.contains("RADROOTS_RETICULUM_ENDPOINT_URI"),
    870         "Reticulum source must consume its preview-owned endpoint URI constant"
    871     );
    872     assert!(
    873         !reticulum_source.contains(["reticulum:", "pre", "view-unavailable"].concat().as_str()),
    874         "Reticulum source must not duplicate its endpoint URI"
    875     );
    876     assert!(
    877         reticulum_source.contains("RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE"),
    878         "Reticulum source must consume its preview-owned unavailable message constant"
    879     );
    880     assert!(
    881         !reticulum_source.contains("Reticulum transport is configured in preview mode"),
    882         "Reticulum source must not duplicate the shared unavailable message"
    883     );
    884     assert!(
    885         !reticulum_source.contains("future compatibility"),
    886         "Reticulum source must not duplicate compatibility copy"
    887     );
    888 
    889     let protocol_source_raw = read_source(
    890         crates_root
    891             .join("protocol/src/radrootsd/transport_publish/v5.rs")
    892             .as_path(),
    893     );
    894     let protocol_source = production_source(protocol_source_raw.as_str());
    895     assert!(
    896         protocol_source.contains("pub const RETICULUM_ENDPOINT_URI: &str = \"reticulum:local\";"),
    897         "versioned transport publish protocol must own its endpoint constant"
    898     );
    899     assert!(
    900         !protocol_source.contains(["reticulum:", "pre", "view-unavailable"].concat().as_str()),
    901         "transport publish protocol must not duplicate the shared endpoint URI"
    902     );
    903     assert!(
    904         protocol_source.contains("pub const RETICULUM_UNAVAILABLE_MESSAGE: &str = concat!("),
    905         "versioned transport publish protocol must own its unavailable message"
    906     );
    907     assert!(
    908         !protocol_source.contains("Reticulum transport is configured in preview mode"),
    909         "transport publish protocol must not duplicate the shared unavailable message"
    910     );
    911     assert!(
    912         !protocol_source.contains("future compatibility"),
    913         "transport publish protocol must not duplicate compatibility copy"
    914     );
    915 }
    916 
    917 fn rust_source_files(root: &Path) -> Vec<PathBuf> {
    918     let mut paths = Vec::new();
    919     collect_rust_source_files(root, &mut paths);
    920     paths.sort();
    921     paths
    922 }
    923 
    924 fn foundation_hardening_guard_files(repo_root: &Path) -> Vec<PathBuf> {
    925     let mut paths = Vec::new();
    926 
    927     for path in [
    928         repo_root.join("Cargo.toml"),
    929         repo_root.join("README"),
    930         repo_root.join("README.md"),
    931     ] {
    932         if path.exists() {
    933             paths.push(path);
    934         }
    935     }
    936 
    937     let crates_root = repo_root.join("crates");
    938     for entry in fs::read_dir(crates_root.as_path())
    939         .unwrap_or_else(|error| panic!("failed to read {}: {error}", crates_root.display()))
    940     {
    941         let path = entry.expect("crate entry").path();
    942         if !path.is_dir() {
    943             continue;
    944         }
    945 
    946         let src = path.join("src");
    947         if src.exists() {
    948             paths.extend(rust_source_files(src.as_path()));
    949         }
    950 
    951         for file_name in ["Cargo.toml", "README", "README.md"] {
    952             let candidate = path.join(file_name);
    953             if candidate.exists() {
    954                 paths.push(candidate);
    955             }
    956         }
    957     }
    958 
    959     for relative_root in FOUNDATION_HARDENING_DOC_ROOTS {
    960         let root = repo_root.join(relative_root);
    961         if root.exists() {
    962             collect_doc_surface_files(root.as_path(), &mut paths);
    963         }
    964     }
    965 
    966     paths.sort();
    967     paths
    968 }
    969 
    970 fn collect_doc_surface_files(root: &Path, paths: &mut Vec<PathBuf>) {
    971     for entry in fs::read_dir(root)
    972         .unwrap_or_else(|error| panic!("failed to read {}: {error}", root.display()))
    973     {
    974         let path = entry.expect("doc surface entry").path();
    975         if path.is_dir() {
    976             collect_doc_surface_files(path.as_path(), paths);
    977             continue;
    978         }
    979 
    980         if is_doc_surface(path.as_path()) {
    981             paths.push(path);
    982         }
    983     }
    984 }
    985 
    986 fn collect_rust_source_files(root: &Path, paths: &mut Vec<PathBuf>) {
    987     for entry in fs::read_dir(root)
    988         .unwrap_or_else(|error| panic!("failed to read {}: {error}", root.display()))
    989     {
    990         let entry = entry.expect("read source entry");
    991         let path = entry.path();
    992         if path.is_dir() {
    993             collect_rust_source_files(path.as_path(), paths);
    994         } else if path.extension().and_then(|extension| extension.to_str()) == Some("rs") {
    995             paths.push(path);
    996         }
    997     }
    998 }
    999 
   1000 fn read_source(path: &Path) -> String {
   1001     fs::read_to_string(path)
   1002         .unwrap_or_else(|error| panic!("failed to read source {}: {error}", path.display()))
   1003 }
   1004 
   1005 fn production_source(source: &str) -> &str {
   1006     source
   1007         .find("\n#[cfg(test)]")
   1008         .map_or(source, |index| &source[..index])
   1009 }
   1010 
   1011 fn is_doc_surface(path: &Path) -> bool {
   1012     matches!(
   1013         path.file_name().and_then(|file_name| file_name.to_str()),
   1014         Some("README") | Some("README.md")
   1015     ) || matches!(
   1016         path.extension().and_then(|extension| extension.to_str()),
   1017         Some("md")
   1018     )
   1019 }
   1020 
   1021 fn relative_path(root: &Path, path: &Path) -> String {
   1022     path.strip_prefix(root)
   1023         .expect("source path is under crate root")
   1024         .to_string_lossy()
   1025         .replace('\\', "/")
   1026 }
   1027 
   1028 fn source_between<'source>(
   1029     source: &'source str,
   1030     start_marker: &str,
   1031     end_marker: &str,
   1032 ) -> &'source str {
   1033     let start = source
   1034         .find(start_marker)
   1035         .unwrap_or_else(|| panic!("failed to find source marker `{start_marker}`"));
   1036     let source_after_start = &source[start..];
   1037     let end = source_after_start
   1038         .find(end_marker)
   1039         .unwrap_or_else(|| panic!("failed to find source marker `{end_marker}`"));
   1040     &source_after_start[..end]
   1041 }
   1042 
   1043 fn contains_forbidden_concept(source: &str, pattern: &str) -> bool {
   1044     if !pattern.chars().all(is_rust_identifier_character) {
   1045         return source.contains(pattern);
   1046     }
   1047 
   1048     source.match_indices(pattern).any(|(index, _)| {
   1049         let before = source[..index].chars().next_back();
   1050         let after = source[index + pattern.len()..].chars().next();
   1051         before.is_none_or(|character| !is_rust_identifier_character(character))
   1052             && after.is_none_or(|character| !is_rust_identifier_character(character))
   1053     })
   1054 }
   1055 
   1056 fn removed_reticulum_stage_endpoint_lines(source: &str) -> Vec<usize> {
   1057     let removed_endpoint_prefix = ["reticulum:", "pre", "view"].concat();
   1058     source
   1059         .match_indices(removed_endpoint_prefix.as_str())
   1060         .filter_map(|(index, _)| {
   1061             let after = source[index + removed_endpoint_prefix.len()..]
   1062                 .chars()
   1063                 .next();
   1064             (after != Some('-')).then(|| line_number(source, index))
   1065         })
   1066         .collect()
   1067 }
   1068 
   1069 fn is_rust_identifier_character(character: char) -> bool {
   1070     character == '_' || character.is_ascii_alphanumeric()
   1071 }
   1072 
   1073 fn line_number(source: &str, index: usize) -> usize {
   1074     source[..index]
   1075         .bytes()
   1076         .filter(|byte| *byte == b'\n')
   1077         .count()
   1078         + 1
   1079 }