lib

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

contract.rs (523532B)


      1 #![forbid(unsafe_code)]
      2 
      3 mod admission_authority;
      4 pub(crate) mod artifact_bundle;
      5 mod comment_authority;
      6 mod deletion_authority;
      7 mod registry_v7;
      8 pub(crate) use registry_v7::{
      9     validate_event_contract_registry_v7_inventory, write_event_contract_registry_v7_inventory,
     10 };
     11 
     12 use crate::coverage::{CoveragePolicyFile, CoverageThresholds, read_coverage_policy};
     13 use admission_authority::validate_admission_operation_authority;
     14 use artifact_bundle::{
     15     GeneratedArtifact, read_regular_file, validate_canonical_json_artifact,
     16     validate_sha256_artifact, with_artifact_bundle_transaction,
     17 };
     18 use comment_authority::{
     19     COMMENT_CASE_KINDS, COMMENT_CONFORMANCE_VECTOR_RELATIVE, COMMENT_OPERATION_EXPECTATIONS,
     20     COMMENT_VECTOR_EXPECTATIONS, REQUIRED_COMMENT_PUBLIC_TYPES,
     21 };
     22 use deletion_authority::{
     23     DELETION_ADMIT_INVALID_IDS, DELETION_ADMIT_VALID_IDS, DELETION_AUTHORED_INVALID_IDS,
     24     DELETION_AUTHORED_VALID_IDS, DELETION_CASE_KINDS, DELETION_CONFORMANCE_VECTOR_RELATIVE,
     25     DELETION_OPERATION_EXPECTATIONS, DELETION_PROJECT_INVALID_IDS, DELETION_PROJECT_VALID_IDS,
     26     DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE, DELETION_SUPPRESSION_VALID_IDS,
     27     REQUIRED_DELETION_PUBLIC_TYPES,
     28 };
     29 use semver::Version;
     30 use serde::{Deserialize, Serialize};
     31 use serde_json::Value;
     32 use sha2::{Digest, Sha256};
     33 use std::collections::{BTreeMap, BTreeSet};
     34 use std::fs;
     35 use std::path::{Path, PathBuf};
     36 use walkdir::WalkDir;
     37 
     38 pub(crate) fn validate_artifact_contracts(workspace_root: &Path) -> Result<(), String> {
     39     validate_event_contract_registry_v7_inventory(workspace_root)?;
     40     validate_knowledge_contract_manifest(workspace_root)
     41 }
     42 
     43 const CONFORMANCE_ROOT_RELATIVE: &str = "contracts/conformance";
     44 const CONFORMANCE_SCHEMA_RELATIVE: &str = "contracts/conformance/schema/vector.schema.json";
     45 const KNOWLEDGE_MANIFEST_RELATIVE: &str =
     46     "contracts/knowledge/knowledge_event_contract_manifest.v2.json";
     47 const KNOWLEDGE_MANIFEST_SHA256_RELATIVE: &str =
     48     "contracts/knowledge/knowledge_event_contract_manifest.v2.sha256";
     49 const KNOWLEDGE_MANIFEST_WRITE_COMMAND: &str = "cargo xtask contract knowledge-manifest --write";
     50 const KNOWLEDGE_MANIFEST_AND_DECODE_RELATIVE: &str =
     51     "contracts/conformance/vectors/knowledge/manifest_and_decode.v1.json";
     52 const KNOWLEDGE_PUBLIC_SURFACE_RELATIVE: &str =
     53     "contracts/conformance/vectors/knowledge/public_surface.v1.json";
     54 const POST_CONFORMANCE_VECTOR_RELATIVE: &str =
     55     "contracts/conformance/vectors/post/verified_profiles.v1.json";
     56 const FOOD_AVAILABILITY_CONFORMANCE_VECTOR_RELATIVE: &str =
     57     "contracts/conformance/vectors/food_availability/profile.v1.json";
     58 const RELEASES_ROOT_RELATIVE: &str = "contracts/releases";
     59 const RELEASE_POLICY_RELATIVE: &str = "contracts/releases/publish_policy.toml";
     60 const SQLITE_RUNTIME_CONTRACT_RELATIVE: &str = "contracts/releases/sqlite_runtime.toml";
     61 const CHANGELOG_RELATIVE: &str = "CHANGELOG.md";
     62 const REPLICA_CONTRACT_RELATIVE: &str = "contracts/replica.toml";
     63 const REPLICA_CONTRACT_NAME: &str = "radroots_replica_contract";
     64 const REPLICA_TRANSFER_CONSTANT: &str = "RADROOTS_REPLICA_TRANSFER_VERSION";
     65 const REPLICA_TRANSFER_VERSION: u32 = 2;
     66 const CONFORMANCE_VECTOR_MIRRORS: [(&str, &str); 19] = [
     67     (
     68         "contracts/conformance/vectors/blossom/bud11_claims.v1.json",
     69         "crates/blossom/tests/fixtures/bud11_claims.v1.json",
     70     ),
     71     (
     72         "contracts/conformance/vectors/blossom/hash_path_and_descriptor.v1.json",
     73         "crates/blossom/tests/fixtures/hash_path_and_descriptor.v1.json",
     74     ),
     75     (
     76         "contracts/conformance/vectors/blossom/bud11_nostr_adapter.v1.json",
     77         "crates/nostr/tests/fixtures/bud11_nostr_adapter.v1.json",
     78     ),
     79     (
     80         "contracts/conformance/vectors/nip17/adapter.v1.json",
     81         "crates/nostr/tests/fixtures/nip17_adapter.v1.json",
     82     ),
     83     (
     84         "contracts/conformance/vectors/calendar/nip52_baseline.v1.json",
     85         "crates/event_codec/tests/fixtures/calendar_nip52_baseline.v1.json",
     86     ),
     87     (
     88         "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
     89         "crates/event_codec/tests/fixtures/calendar_radroots_profile.v1.json",
     90     ),
     91     (
     92         "contracts/conformance/vectors/comment/verified_profile.v1.json",
     93         "crates/event_codec/tests/fixtures/comment_verified_profile.v1.json",
     94     ),
     95     (
     96         "contracts/conformance/vectors/deletion/verified_profile.v1.json",
     97         "crates/event_codec/tests/fixtures/deletion_verified_profile.v1.json",
     98     ),
     99     (
    100         "contracts/conformance/vectors/deletion/suppression.v1.json",
    101         "crates/event_codec/tests/fixtures/deletion_suppression.v1.json",
    102     ),
    103     (
    104         "contracts/conformance/vectors/event/verified_admission.v1.json",
    105         "crates/event_codec/tests/fixtures/verified_admission.v1.json",
    106     ),
    107     (
    108         "contracts/conformance/vectors/event/authored_plan_wire.v1.json",
    109         "crates/event_codec/tests/fixtures/authored_plan_wire.v1.json",
    110     ),
    111     (
    112         "contracts/conformance/vectors/events/operational_listing_tags_full.v1.json",
    113         "crates/event_codec/tests/fixtures/operational_listing_tags_full.v1.json",
    114     ),
    115     (
    116         "contracts/conformance/vectors/food_availability/profile.v1.json",
    117         "crates/event_codec/tests/fixtures/food_availability_profile.v1.json",
    118     ),
    119     (
    120         "contracts/conformance/vectors/operational_listing/build_draft.v1.json",
    121         "crates/event_codec/tests/fixtures/operational_listing_build_draft.v1.json",
    122     ),
    123     (
    124         "contracts/conformance/vectors/operational_listing/build_tags.v1.json",
    125         "crates/event_codec/tests/fixtures/operational_listing_build_tags.v1.json",
    126     ),
    127     (
    128         "contracts/conformance/vectors/operational_listing/parse_event.v1.json",
    129         "crates/event_codec/tests/fixtures/operational_listing_parse_event.v1.json",
    130     ),
    131     (
    132         "contracts/conformance/vectors/profile/metadata.v1.json",
    133         "crates/event_codec/tests/fixtures/profile_metadata.v1.json",
    134     ),
    135     (
    136         "contracts/conformance/vectors/profile/verified_event.v1.json",
    137         "crates/event_codec/tests/fixtures/profile_verified_event.v1.json",
    138     ),
    139     (
    140         "contracts/conformance/vectors/post/verified_profiles.v1.json",
    141         "crates/event_codec/tests/fixtures/post_verified_profiles.v1.json",
    142     ),
    143 ];
    144 const KNOWLEDGE_MVP_SUPPORT_CONTRACT_IDS: [&str; 8] = [
    145     "radroots.wiki.article.v1",
    146     "radroots.wiki.redirect.v1",
    147     "radroots.wiki.merge_request.v1",
    148     "radroots.knowledge.source.v1",
    149     "radroots.knowledge.claim.v1",
    150     "radroots.knowledge.relation.v1",
    151     "radroots.knowledge.review.v1",
    152     "radroots.knowledge.field_report.v1",
    153 ];
    154 const KNOWLEDGE_BETA_CONTRACT_IDS: [&str; 3] = [
    155     "radroots.knowledge.evidence_bounty.v1",
    156     "radroots.knowledge.change_proposal.v1",
    157     "radroots.knowledge.contribution_attestation.v1",
    158 ];
    159 const EVENT_BOUNDARY_MATRIX_RELATIVE: &str = "contracts/event_boundary_matrix.md";
    160 const COVERAGE_REQUIRED_THRESHOLD: f64 = 90.0;
    161 const COVERAGE_REQUIRED_THRESHOLD_LABEL: &str = "90/90/90/90";
    162 const COVERAGE_REPORT_EPSILON: f64 = 0.000_001;
    163 const DTO_TOOLING_DEPENDENCIES: [&str; 4] = [
    164     "dto_bindgen",
    165     "dto_bindgen_backend_ts",
    166     "dto_bindgen_core",
    167     "dto_bindgen_macros",
    168 ];
    169 const RETIRED_OPERATION_EVENT_NAMES: [&str; 15] = [
    170     "WireEventParts",
    171     "RadrootsFrozenEventDraft",
    172     "RadrootsNostrEvent",
    173     "RadrootsNostrEventRef",
    174     "RadrootsNostrEventPtr",
    175     "RadrootsCalendarDateEvent",
    176     "RadrootsCalendarTimeEvent",
    177     "RadrootsCalendarDateValue",
    178     "RadrootsInboundCalendarDateEvent",
    179     "RadrootsInboundCalendarTimeEvent",
    180     "RadrootsCalendar",
    181     "RadrootsCalendarEventRsvp",
    182     "RadrootsCalendarRsvp",
    183     "RadrootsComment",
    184     "RadrootsNip10RelayHint",
    185 ];
    186 const REQUIRED_CALENDAR_PUBLIC_TYPES: [&str; 34] = [
    187     "Nip01EventWireParts",
    188     "BlobUrl",
    189     "AuthoredImage",
    190     "AuthoredImageError",
    191     "IanaTimeZoneId",
    192     "CalendarUri",
    193     "CalendarRequest",
    194     "CalendarParticipant",
    195     "CalendarEventError",
    196     "CalendarDate",
    197     "AuthoredCalendarDateEvent",
    198     "AuthoredCalendarTimeEvent",
    199     "ParsedNip52CalendarCommon",
    200     "ParsedNip52CalendarCommonParts",
    201     "ParsedNip52CalendarDateEvent",
    202     "ObservedUtcDay",
    203     "ParsedNip52CalendarTimeEvent",
    204     "CalendarAdmissionError",
    205     "AdmittedCalendarDateEvent",
    206     "AdmittedCalendarTimeEvent",
    207     "CalendarUid",
    208     "CalendarEventReference",
    209     "CalendarEventRevisionReference",
    210     "CalendarEventAuthorReference",
    211     "AuthoredCalendar",
    212     "ParsedNip52CalendarParts",
    213     "ParsedNip52Calendar",
    214     "AdmittedCalendar",
    215     "CalendarEventRsvpStatus",
    216     "CalendarEventFreeBusy",
    217     "AuthoredCalendarEventRsvp",
    218     "ParsedNip52CalendarEventRsvpParts",
    219     "ParsedNip52CalendarEventRsvp",
    220     "AdmittedCalendarEventRsvp",
    221 ];
    222 const REQUIRED_POST_PUBLIC_TYPES: [&str; 34] = [
    223     "ApprovedBlobUrl",
    224     "ByteVerifiedDescriptor",
    225     "Nip01EventWireParts",
    226     "EventEnvelope",
    227     "RadrootsSignatureVerifiedEvent",
    228     "AuthoredImage",
    229     "Post",
    230     "AuthoredPostError",
    231     "PostImageDimensions",
    232     "AuthoredPostImage",
    233     "AuthoredUpdate",
    234     "AuthoredPhotoUpdate",
    235     "AuthoredAsk",
    236     "Nip10ReplyError",
    237     "NostrRelayHint",
    238     "Nip10ReplyReference",
    239     "AuthoredNip10Reply",
    240     "RadrootsPostDiagnostic",
    241     "RadrootsPostClassification",
    242     "RadrootsInboundPostImeta",
    243     "RadrootsInboundPostProjection",
    244     "RadrootsPostProjectionError",
    245     "RadrootsAdmittedRootPostEvent",
    246     "RadrootsThreadExcludedPostCandidate",
    247     "RadrootsPostAdmissionOutcome",
    248     "RadrootsPostAdmissionError",
    249     "RadrootsNip10ReplyStyle",
    250     "RadrootsNip10ReplyDiagnostic",
    251     "RadrootsInboundNip10EventReference",
    252     "RadrootsInboundNip10Participant",
    253     "RadrootsInboundNip10ReplyProjection",
    254     "RadrootsNip10ReplyProjectionError",
    255     "RadrootsAdmittedNip10ReplyEvent",
    256     "RadrootsNip10ReplyAdmissionError",
    257 ];
    258 const REQUIRED_FOOD_AVAILABILITY_PUBLIC_TYPES: [&str; 31] = [
    259     "ByteVerifiedDescriptor",
    260     "Nip01EventWireParts",
    261     "EventEnvelope",
    262     "RadrootsSignatureVerifiedEvent",
    263     "ClassifiedListingPartition",
    264     "AuthoredImage",
    265     "FoodAvailabilityError",
    266     "FoodContent",
    267     "FoodIdentifier",
    268     "FoodText",
    269     "FoodPublishedAt",
    270     "FoodCurrency",
    271     "FoodUnit",
    272     "FoodPrice",
    273     "FoodQuantity",
    274     "FoodAvailabilityStatus",
    275     "FoodImageDimensions",
    276     "FoodAvailabilityImage",
    277     "FoodAvailabilityDetailsParts",
    278     "FoodAvailabilityDetails",
    279     "RadrootsFoodAvailabilityEncodeError",
    280     "RadrootsFoodAvailabilityImageDiagnostic",
    281     "RadrootsInboundFoodAvailabilityImage",
    282     "RadrootsInboundFoodAvailabilityProjection",
    283     "RadrootsFoodAvailabilityProjectionOutcome",
    284     "RadrootsFoodAvailabilityProjectionError",
    285     "RadrootsAdmittedFoodAvailabilityEvent",
    286     "RadrootsExcludedClassifiedListingCandidate",
    287     "RadrootsFoodAvailabilityAdmissionOutcome",
    288     "RadrootsFoodAvailabilityAdmissionError",
    289     "RadrootsFoodAvailabilityRevisionError",
    290 ];
    291 const CALENDAR_OPERATION_EXPECTATIONS: [CalendarOperationExpectation; 12] = [
    292     CalendarOperationExpectation {
    293         key: "social_calendar_date_event_build_authored_draft",
    294         id: "social.calendar_date_event.build_authored_draft",
    295         inputs: &["AuthoredCalendarDateEvent"],
    296         outputs: &["Nip01EventWireParts"],
    297         error_class: "encode_error",
    298         rust_modules: &[
    299             "crates/event/src/calendar.rs",
    300             "crates/event/src/media.rs",
    301             "crates/event_codec/src/calendar/encode.rs",
    302         ],
    303         rust_types: &[
    304             "radroots_event::calendar::AuthoredCalendarDateEvent",
    305             "radroots_event::calendar::CalendarDate",
    306             "radroots_event::calendar::CalendarEventError",
    307             "radroots_event::media::AuthoredImage",
    308             "radroots_event::wire::Nip01EventWireParts",
    309             "radroots_event_codec::error::EventEncodeError",
    310         ],
    311         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    312     },
    313     CalendarOperationExpectation {
    314         key: "social_calendar_date_event_parse_nip52",
    315         id: "social.calendar_date_event.parse_nip52",
    316         inputs: &["u32", "NostrTags", "String"],
    317         outputs: &["ParsedNip52CalendarDateEvent"],
    318         error_class: "parse_error",
    319         rust_modules: &[
    320             "crates/event/src/calendar.rs",
    321             "crates/event_codec/src/calendar/decode.rs",
    322         ],
    323         rust_types: &[
    324             "radroots_event::calendar::CalendarDate",
    325             "radroots_event::calendar::CalendarRequest",
    326             "radroots_event::calendar::CalendarUri",
    327             "radroots_event::calendar::ParsedNip52CalendarCommon",
    328             "radroots_event::calendar::ParsedNip52CalendarCommonParts",
    329             "radroots_event::calendar::ParsedNip52CalendarDateEvent",
    330             "radroots_event_codec::error::EventParseError",
    331         ],
    332         vector: "contracts/conformance/vectors/calendar/nip52_baseline.v1.json",
    333     },
    334     CalendarOperationExpectation {
    335         key: "social_calendar_date_event_admit_radroots_profile",
    336         id: "social.calendar_date_event.admit_radroots_profile",
    337         inputs: &["ParsedNip52CalendarDateEvent"],
    338         outputs: &["AdmittedCalendarDateEvent"],
    339         error_class: "admission_error",
    340         rust_modules: &[
    341             "crates/event/src/calendar.rs",
    342             "crates/event_codec/src/calendar/decode.rs",
    343         ],
    344         rust_types: &[
    345             "radroots_event::calendar::AdmittedCalendarDateEvent",
    346             "radroots_event::calendar::CalendarAdmissionError",
    347             "radroots_event::calendar::ParsedNip52CalendarDateEvent",
    348         ],
    349         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    350     },
    351     CalendarOperationExpectation {
    352         key: "social_calendar_time_event_build_authored_draft",
    353         id: "social.calendar_time_event.build_authored_draft",
    354         inputs: &["AuthoredCalendarTimeEvent"],
    355         outputs: &["Nip01EventWireParts"],
    356         error_class: "encode_error",
    357         rust_modules: &[
    358             "crates/event/src/calendar.rs",
    359             "crates/event/src/media.rs",
    360             "crates/event_codec/src/calendar/encode.rs",
    361         ],
    362         rust_types: &[
    363             "radroots_event::calendar::AuthoredCalendarTimeEvent",
    364             "radroots_event::calendar::CalendarEventError",
    365             "radroots_event::calendar::IanaTimeZoneId",
    366             "radroots_event::media::AuthoredImage",
    367             "radroots_event::wire::Nip01EventWireParts",
    368             "radroots_event_codec::error::EventEncodeError",
    369         ],
    370         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    371     },
    372     CalendarOperationExpectation {
    373         key: "social_calendar_time_event_parse_nip52",
    374         id: "social.calendar_time_event.parse_nip52",
    375         inputs: &["u32", "NostrTags", "String"],
    376         outputs: &["ParsedNip52CalendarTimeEvent"],
    377         error_class: "parse_error",
    378         rust_modules: &[
    379             "crates/event/src/calendar.rs",
    380             "crates/event_codec/src/calendar/decode.rs",
    381         ],
    382         rust_types: &[
    383             "radroots_event::calendar::CalendarRequest",
    384             "radroots_event::calendar::CalendarUri",
    385             "radroots_event::calendar::IanaTimeZoneId",
    386             "radroots_event::calendar::ObservedUtcDay",
    387             "radroots_event::calendar::ParsedNip52CalendarCommon",
    388             "radroots_event::calendar::ParsedNip52CalendarCommonParts",
    389             "radroots_event::calendar::ParsedNip52CalendarTimeEvent",
    390             "radroots_event_codec::error::EventParseError",
    391         ],
    392         vector: "contracts/conformance/vectors/calendar/nip52_baseline.v1.json",
    393     },
    394     CalendarOperationExpectation {
    395         key: "social_calendar_time_event_admit_radroots_profile",
    396         id: "social.calendar_time_event.admit_radroots_profile",
    397         inputs: &["ParsedNip52CalendarTimeEvent"],
    398         outputs: &["AdmittedCalendarTimeEvent"],
    399         error_class: "admission_error",
    400         rust_modules: &[
    401             "crates/event/src/calendar.rs",
    402             "crates/event_codec/src/calendar/decode.rs",
    403         ],
    404         rust_types: &[
    405             "radroots_event::calendar::AdmittedCalendarTimeEvent",
    406             "radroots_event::calendar::CalendarAdmissionError",
    407             "radroots_event::calendar::ParsedNip52CalendarTimeEvent",
    408         ],
    409         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    410     },
    411     CalendarOperationExpectation {
    412         key: "social_calendar_build_authored_draft",
    413         id: "social.calendar.build_authored_draft",
    414         inputs: &["AuthoredCalendar"],
    415         outputs: &["Nip01EventWireParts"],
    416         error_class: "encode_error",
    417         rust_modules: &[
    418             "crates/event/src/calendar.rs",
    419             "crates/event/src/media.rs",
    420             "crates/event_codec/src/calendar/encode.rs",
    421         ],
    422         rust_types: &[
    423             "radroots_event::calendar::AuthoredCalendar",
    424             "radroots_event::calendar::CalendarEventError",
    425             "radroots_event::calendar::CalendarEventReference",
    426             "radroots_event::calendar::CalendarUid",
    427             "radroots_event::media::AuthoredImage",
    428             "radroots_event::wire::Nip01EventWireParts",
    429             "radroots_event_codec::error::EventEncodeError",
    430         ],
    431         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    432     },
    433     CalendarOperationExpectation {
    434         key: "social_calendar_parse_nip52",
    435         id: "social.calendar.parse_nip52",
    436         inputs: &["u32", "NostrTags", "String"],
    437         outputs: &["ParsedNip52Calendar"],
    438         error_class: "parse_error",
    439         rust_modules: &[
    440             "crates/event/src/calendar.rs",
    441             "crates/event_codec/src/calendar/decode.rs",
    442         ],
    443         rust_types: &[
    444             "radroots_event::calendar::CalendarEventError",
    445             "radroots_event::calendar::CalendarEventReference",
    446             "radroots_event::calendar::CalendarUri",
    447             "radroots_event::calendar::ParsedNip52Calendar",
    448             "radroots_event::calendar::ParsedNip52CalendarParts",
    449             "radroots_event_codec::error::EventParseError",
    450         ],
    451         vector: "contracts/conformance/vectors/calendar/nip52_baseline.v1.json",
    452     },
    453     CalendarOperationExpectation {
    454         key: "social_calendar_admit_radroots_profile",
    455         id: "social.calendar.admit_radroots_profile",
    456         inputs: &["ParsedNip52Calendar"],
    457         outputs: &["AdmittedCalendar"],
    458         error_class: "admission_error",
    459         rust_modules: &[
    460             "crates/event/src/calendar.rs",
    461             "crates/event_codec/src/calendar/decode.rs",
    462         ],
    463         rust_types: &[
    464             "radroots_blossom::BlobUrl",
    465             "radroots_event::calendar::AdmittedCalendar",
    466             "radroots_event::calendar::CalendarAdmissionError",
    467             "radroots_event::calendar::CalendarEventReference",
    468             "radroots_event::calendar::CalendarUid",
    469             "radroots_event::calendar::ParsedNip52Calendar",
    470         ],
    471         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    472     },
    473     CalendarOperationExpectation {
    474         key: "social_calendar_rsvp_build_authored_draft",
    475         id: "social.calendar_rsvp.build_authored_draft",
    476         inputs: &["AuthoredCalendarEventRsvp"],
    477         outputs: &["Nip01EventWireParts"],
    478         error_class: "encode_error",
    479         rust_modules: &[
    480             "crates/event/src/calendar.rs",
    481             "crates/event_codec/src/calendar/encode.rs",
    482         ],
    483         rust_types: &[
    484             "radroots_event::calendar::AuthoredCalendarEventRsvp",
    485             "radroots_event::calendar::CalendarEventAuthorReference",
    486             "radroots_event::calendar::CalendarEventError",
    487             "radroots_event::calendar::CalendarEventReference",
    488             "radroots_event::calendar::CalendarEventRevisionReference",
    489             "radroots_event::calendar::CalendarUid",
    490             "radroots_event::calendar::CalendarEventFreeBusy",
    491             "radroots_event::calendar::CalendarEventRsvpStatus",
    492             "radroots_event::wire::Nip01EventWireParts",
    493             "radroots_event_codec::error::EventEncodeError",
    494         ],
    495         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    496     },
    497     CalendarOperationExpectation {
    498         key: "social_calendar_rsvp_parse_nip52",
    499         id: "social.calendar_rsvp.parse_nip52",
    500         inputs: &["u32", "NostrTags", "String"],
    501         outputs: &["ParsedNip52CalendarEventRsvp"],
    502         error_class: "parse_error",
    503         rust_modules: &[
    504             "crates/event/src/calendar.rs",
    505             "crates/event_codec/src/calendar/decode.rs",
    506         ],
    507         rust_types: &[
    508             "radroots_event::calendar::CalendarEventAuthorReference",
    509             "radroots_event::calendar::CalendarEventError",
    510             "radroots_event::calendar::CalendarEventReference",
    511             "radroots_event::calendar::CalendarEventRevisionReference",
    512             "radroots_event::calendar::ParsedNip52CalendarEventRsvp",
    513             "radroots_event::calendar::ParsedNip52CalendarEventRsvpParts",
    514             "radroots_event::calendar::CalendarEventFreeBusy",
    515             "radroots_event::calendar::CalendarEventRsvpStatus",
    516             "radroots_event_codec::error::EventParseError",
    517         ],
    518         vector: "contracts/conformance/vectors/calendar/nip52_baseline.v1.json",
    519     },
    520     CalendarOperationExpectation {
    521         key: "social_calendar_rsvp_admit_radroots_profile",
    522         id: "social.calendar_rsvp.admit_radroots_profile",
    523         inputs: &["ParsedNip52CalendarEventRsvp"],
    524         outputs: &["AdmittedCalendarEventRsvp"],
    525         error_class: "admission_error",
    526         rust_modules: &[
    527             "crates/event/src/calendar.rs",
    528             "crates/event_codec/src/calendar/decode.rs",
    529         ],
    530         rust_types: &[
    531             "radroots_event::calendar::AdmittedCalendarEventRsvp",
    532             "radroots_event::calendar::CalendarAdmissionError",
    533             "radroots_event::calendar::CalendarEventAuthorReference",
    534             "radroots_event::calendar::CalendarEventReference",
    535             "radroots_event::calendar::CalendarEventRevisionReference",
    536             "radroots_event::calendar::CalendarUid",
    537             "radroots_event::calendar::ParsedNip52CalendarEventRsvp",
    538             "radroots_event::calendar::CalendarEventFreeBusy",
    539             "radroots_event::calendar::CalendarEventRsvpStatus",
    540         ],
    541         vector: "contracts/conformance/vectors/calendar/radroots_profile.v1.json",
    542     },
    543 ];
    544 const POST_OPERATION_EXPECTATIONS: [PostOperationExpectation; 8] = [
    545     PostOperationExpectation {
    546         key: "social_update_build_authored_draft",
    547         id: "social.update.build_authored_draft",
    548         inputs: &["AuthoredUpdate"],
    549         outputs: &["Nip01EventWireParts"],
    550         error_class: "encode_error",
    551         signing: "none",
    552         rust_modules: &[
    553             "crates/event/src/post.rs",
    554             "crates/event_codec/src/post/authored.rs",
    555         ],
    556         rust_types: &[
    557             "radroots_event::post::AuthoredPostError",
    558             "radroots_event::post::AuthoredUpdate",
    559         ],
    560         case_kinds: &[
    561             "social.update.build_authored_draft.valid",
    562             "social.update.build_authored_draft.invalid",
    563         ],
    564     },
    565     PostOperationExpectation {
    566         key: "social_photo_update_build_authored_draft",
    567         id: "social.photo_update.build_authored_draft",
    568         inputs: &["AuthoredPhotoUpdate"],
    569         outputs: &["Nip01EventWireParts"],
    570         error_class: "encode_error",
    571         signing: "none",
    572         rust_modules: &[
    573             "crates/event/src/post.rs",
    574             "crates/event_codec/src/post/authored.rs",
    575         ],
    576         rust_types: &[
    577             "radroots_blossom::ApprovedBlobUrl",
    578             "radroots_blossom::ByteVerifiedDescriptor",
    579             "radroots_event::media::AuthoredImage",
    580             "radroots_event::post::AuthoredPhotoUpdate",
    581             "radroots_event::post::AuthoredPostError",
    582             "radroots_event::post::AuthoredPostImage",
    583             "radroots_event::post::PostImageDimensions",
    584         ],
    585         case_kinds: &[
    586             "social.photo_update.build_authored_draft.valid",
    587             "social.photo_update.build_authored_draft.invalid",
    588         ],
    589     },
    590     PostOperationExpectation {
    591         key: "social_ask_build_authored_draft",
    592         id: "social.ask.build_authored_draft",
    593         inputs: &["AuthoredAsk"],
    594         outputs: &["Nip01EventWireParts"],
    595         error_class: "encode_error",
    596         signing: "none",
    597         rust_modules: &[
    598             "crates/event/src/post.rs",
    599             "crates/event_codec/src/post/authored.rs",
    600         ],
    601         rust_types: &[
    602             "radroots_event::post::AuthoredAsk",
    603             "radroots_event::post::AuthoredPostError",
    604             "radroots_event::post::AuthoredPostImage",
    605         ],
    606         case_kinds: &[
    607             "social.ask.build_authored_draft.valid",
    608             "social.ask.build_authored_draft.invalid",
    609         ],
    610     },
    611     PostOperationExpectation {
    612         key: "social_reply_build_authored_draft",
    613         id: "social.reply.build_authored_draft",
    614         inputs: &["AuthoredNip10Reply"],
    615         outputs: &["Nip01EventWireParts"],
    616         error_class: "encode_error",
    617         signing: "none",
    618         rust_modules: &[
    619             "crates/event/src/relay_hint.rs",
    620             "crates/event/src/reply.rs",
    621             "crates/event_codec/src/reply/authored.rs",
    622         ],
    623         rust_types: &[
    624             "radroots_event::post::reply::AuthoredNip10Reply",
    625             "radroots_event::post::reply::Nip10ReplyError",
    626             "radroots_event::tag::relay_hint::NostrRelayHint",
    627             "radroots_event::post::reply::Nip10ReplyReference",
    628         ],
    629         case_kinds: &[
    630             "social.reply.build_authored_draft.valid",
    631             "social.reply.build_authored_draft.invalid",
    632         ],
    633     },
    634     PostOperationExpectation {
    635         key: "social_reply_project_verified_event",
    636         id: "social.reply.project_verified_event",
    637         inputs: &["RadrootsSignatureVerifiedEvent"],
    638         outputs: &["RadrootsInboundNip10ReplyProjection"],
    639         error_class: "parse_error",
    640         signing: "none",
    641         rust_modules: &[
    642             "crates/event/src/relay_hint.rs",
    643             "crates/event_codec/src/reply/inbound.rs",
    644         ],
    645         rust_types: &[
    646             "radroots_event::tag::relay_hint::NostrRelayHint",
    647             "radroots_event_codec::decode::reply::RadrootsInboundNip10EventReference",
    648             "radroots_event_codec::decode::reply::RadrootsInboundNip10Participant",
    649             "radroots_event_codec::decode::reply::RadrootsInboundNip10ReplyProjection",
    650             "radroots_event_codec::decode::reply::RadrootsNip10ReplyDiagnostic",
    651             "radroots_event_codec::decode::reply::RadrootsNip10ReplyProjectionError",
    652             "radroots_event_codec::decode::reply::RadrootsNip10ReplyStyle",
    653             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
    654         ],
    655         case_kinds: &[
    656             "social.reply.project_verified_event.valid",
    657             "social.reply.project_verified_event.invalid",
    658         ],
    659     },
    660     PostOperationExpectation {
    661         key: "social_reply_verify_and_admit_event",
    662         id: "social.reply.verify_and_admit_event",
    663         inputs: &["EventEnvelope"],
    664         outputs: &["RadrootsAdmittedNip10ReplyEvent"],
    665         error_class: "admission_error",
    666         signing: "nip01",
    667         rust_modules: &[
    668             "crates/event_codec/src/reply/admission.rs",
    669             "crates/event_codec/src/reply/inbound.rs",
    670             "crates/event_codec/src/verification.rs",
    671         ],
    672         rust_types: &[
    673             "radroots_event::envelope::EventEnvelope",
    674             "radroots_event_codec::admission::reply::RadrootsAdmittedNip10ReplyEvent",
    675             "radroots_event_codec::admission::reply::RadrootsNip10ReplyAdmissionError",
    676             "radroots_event_codec::decode::reply::RadrootsInboundNip10ReplyProjection",
    677             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
    678         ],
    679         case_kinds: &[
    680             "social.reply.verify_and_admit_event.valid",
    681             "social.reply.verify_and_admit_event.invalid",
    682         ],
    683     },
    684     PostOperationExpectation {
    685         key: "social_post_project_verified_event",
    686         id: "social.post.project_verified_event",
    687         inputs: &["RadrootsSignatureVerifiedEvent"],
    688         outputs: &["RadrootsInboundPostProjection"],
    689         error_class: "parse_error",
    690         signing: "none",
    691         rust_modules: &["crates/event_codec/src/post/inbound.rs"],
    692         rust_types: &[
    693             "radroots_event_codec::decode::post::RadrootsInboundPostImeta",
    694             "radroots_event_codec::decode::post::RadrootsInboundPostProjection",
    695             "radroots_event_codec::decode::post::RadrootsPostClassification",
    696             "radroots_event_codec::decode::post::RadrootsPostDiagnostic",
    697             "radroots_event_codec::decode::post::RadrootsPostProjectionError",
    698             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
    699         ],
    700         case_kinds: &[
    701             "social.post.project_verified_event.valid",
    702             "social.post.project_verified_event.invalid",
    703         ],
    704     },
    705     PostOperationExpectation {
    706         key: "social_post_verify_and_admit_event",
    707         id: "social.post.verify_and_admit_event",
    708         inputs: &["EventEnvelope"],
    709         outputs: &["RadrootsPostAdmissionOutcome"],
    710         error_class: "admission_error",
    711         signing: "nip01",
    712         rust_modules: &[
    713             "crates/event_codec/src/post/admission.rs",
    714             "crates/event_codec/src/post/inbound.rs",
    715             "crates/event_codec/src/verification.rs",
    716         ],
    717         rust_types: &[
    718             "radroots_event::envelope::EventEnvelope",
    719             "radroots_event_codec::admission::post::RadrootsAdmittedRootPostEvent",
    720             "radroots_event_codec::admission::post::RadrootsPostAdmissionError",
    721             "radroots_event_codec::admission::post::RadrootsPostAdmissionOutcome",
    722             "radroots_event_codec::admission::post::RadrootsThreadExcludedPostCandidate",
    723             "radroots_event_codec::decode::post::RadrootsInboundPostProjection",
    724             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
    725         ],
    726         case_kinds: &[
    727             "social.post.verify_and_admit_event.valid",
    728             "social.post.verify_and_admit_event.invalid",
    729         ],
    730     },
    731 ];
    732 const POST_OPERATION_KEY_PREFIXES: [&str; 5] = [
    733     "social_update_",
    734     "social_photo_update_",
    735     "social_ask_",
    736     "social_reply_",
    737     "social_post_",
    738 ];
    739 const POST_OPERATION_ID_PREFIXES: [&str; 5] = [
    740     "social.update.",
    741     "social.photo_update.",
    742     "social.ask.",
    743     "social.reply.",
    744     "social.post.",
    745 ];
    746 const POST_VECTOR_EXPECTATIONS: [(&str, &str); 64] = [
    747     (
    748         "authored_update_wire",
    749         "social.update.build_authored_draft.valid",
    750     ),
    751     (
    752         "authored_update_blank",
    753         "social.update.build_authored_draft.invalid",
    754     ),
    755     (
    756         "authored_photo_update_wire",
    757         "social.photo_update.build_authored_draft.valid",
    758     ),
    759     (
    760         "authored_photo_update_mime_underscore",
    761         "social.photo_update.build_authored_draft.invalid",
    762     ),
    763     ("authored_ask_wire", "social.ask.build_authored_draft.valid"),
    764     (
    765         "authored_ask_blank",
    766         "social.ask.build_authored_draft.invalid",
    767     ),
    768     (
    769         "authored_nip10_direct_wire",
    770         "social.reply.build_authored_draft.valid",
    771     ),
    772     (
    773         "authored_nip10_nested_wire",
    774         "social.reply.build_authored_draft.valid",
    775     ),
    776     (
    777         "authored_nip10_canonical_ipv6_relay",
    778         "social.reply.build_authored_draft.valid",
    779     ),
    780     (
    781         "authored_nip10_ambiguous_parent",
    782         "social.reply.build_authored_draft.invalid",
    783     ),
    784     (
    785         "authored_nip10_invalid_event_id",
    786         "social.reply.build_authored_draft.invalid",
    787     ),
    788     (
    789         "authored_nip10_invalid_relay_percent_host",
    790         "social.reply.build_authored_draft.invalid",
    791     ),
    792     (
    793         "authored_nip10_invalid_relay_bad_percent_host",
    794         "social.reply.build_authored_draft.invalid",
    795     ),
    796     (
    797         "authored_nip10_invalid_relay_ipv4_overflow",
    798         "social.reply.build_authored_draft.invalid",
    799     ),
    800     (
    801         "authored_nip10_invalid_relay_ipvfuture",
    802         "social.reply.build_authored_draft.invalid",
    803     ),
    804     (
    805         "authored_nip10_invalid_relay_empty_port",
    806         "social.reply.build_authored_draft.invalid",
    807     ),
    808     (
    809         "authored_nip10_invalid_relay_zero_port",
    810         "social.reply.build_authored_draft.invalid",
    811     ),
    812     (
    813         "authored_nip10_invalid_relay_port_overflow",
    814         "social.reply.build_authored_draft.invalid",
    815     ),
    816     (
    817         "project_signed_nip10_marked_direct",
    818         "social.reply.project_verified_event.valid",
    819     ),
    820     (
    821         "project_signed_nip10_marked_with_citation",
    822         "social.reply.project_verified_event.valid",
    823     ),
    824     (
    825         "project_signed_nip10_marked_with_malformed_citation",
    826         "social.reply.project_verified_event.valid",
    827     ),
    828     (
    829         "project_signed_nip10_marked_nested_reordered",
    830         "social.reply.project_verified_event.valid",
    831     ),
    832     (
    833         "project_signed_nip10_positional_direct",
    834         "social.reply.project_verified_event.valid",
    835     ),
    836     (
    837         "project_signed_nip10_positional_direct_with_author_hint",
    838         "social.reply.project_verified_event.valid",
    839     ),
    840     (
    841         "project_signed_nip10_positional_many",
    842         "social.reply.project_verified_event.valid",
    843     ),
    844     (
    845         "project_signed_nip10_positional_many_with_author_hints",
    846         "social.reply.project_verified_event.valid",
    847     ),
    848     (
    849         "project_signed_nip10_positional_malformed_middle_citation",
    850         "social.reply.project_verified_event.valid",
    851     ),
    852     (
    853         "project_signed_nip10_precedes_ask_and_media",
    854         "social.reply.project_verified_event.valid",
    855     ),
    856     (
    857         "project_signed_nip10_invalid_relay",
    858         "social.reply.project_verified_event.valid",
    859     ),
    860     (
    861         "project_signed_nip10_canonical_relay_authorities",
    862         "social.reply.project_verified_event.valid",
    863     ),
    864     (
    865         "project_signed_nip10_malformed_relay_authorities",
    866         "social.reply.project_verified_event.valid",
    867     ),
    868     (
    869         "project_signed_nip10_ambiguous_same_reference",
    870         "social.reply.project_verified_event.invalid",
    871     ),
    872     (
    873         "project_signed_nip10_missing_author",
    874         "social.reply.project_verified_event.valid",
    875     ),
    876     (
    877         "project_signed_nip10_invalid_event_id",
    878         "social.reply.project_verified_event.invalid",
    879     ),
    880     (
    881         "project_signed_nip10_author_hint_mismatch",
    882         "social.reply.project_verified_event.valid",
    883     ),
    884     (
    885         "project_signed_nip10_blank_content",
    886         "social.reply.project_verified_event.valid",
    887     ),
    888     (
    889         "project_signed_nip10_invalid_author_hint_tolerated",
    890         "social.reply.project_verified_event.valid",
    891     ),
    892     (
    893         "project_signed_nip10_invalid_participant_tolerated",
    894         "social.reply.project_verified_event.valid",
    895     ),
    896     (
    897         "project_signed_nip10_lone_reply_marker",
    898         "social.reply.project_verified_event.invalid",
    899     ),
    900     (
    901         "project_signed_nip10_unknown_marker",
    902         "social.reply.project_verified_event.invalid",
    903     ),
    904     (
    905         "admit_signed_nip10_marked_direct",
    906         "social.reply.verify_and_admit_event.valid",
    907     ),
    908     (
    909         "admit_signed_nip10_positional_direct",
    910         "social.reply.verify_and_admit_event.valid",
    911     ),
    912     (
    913         "admit_signed_nip10_invalid_signature",
    914         "social.reply.verify_and_admit_event.invalid",
    915     ),
    916     (
    917         "project_signed_update",
    918         "social.post.project_verified_event.valid",
    919     ),
    920     (
    921         "project_signed_empty_inbound_update",
    922         "social.post.project_verified_event.valid",
    923     ),
    924     (
    925         "project_signed_structural_photo",
    926         "social.post.project_verified_event.valid",
    927     ),
    928     (
    929         "project_signed_photo_preserves_fallbacks_and_unknown_fields",
    930         "social.post.project_verified_event.valid",
    931     ),
    932     (
    933         "project_signed_normalized_ask_precedes_malformed_media",
    934         "social.post.project_verified_event.valid",
    935     ),
    936     (
    937         "project_signed_malformed_imeta_is_update",
    938         "social.post.project_verified_event.valid",
    939     ),
    940     (
    941         "project_signed_duplicate_singleton_is_update",
    942         "social.post.project_verified_event.valid",
    943     ),
    944     (
    945         "project_signed_mixed_imeta_is_update",
    946         "social.post.project_verified_event.valid",
    947     ),
    948     (
    949         "project_signed_thread_candidate_precedes_ask_and_media",
    950         "social.post.project_verified_event.valid",
    951     ),
    952     (
    953         "project_signed_malformed_ask_marker_is_update",
    954         "social.post.project_verified_event.valid",
    955     ),
    956     (
    957         "project_signed_duplicate_normalized_ask_marker",
    958         "social.post.project_verified_event.invalid",
    959     ),
    960     (
    961         "project_signed_kind_20_is_not_photo_update",
    962         "social.post.project_verified_event.invalid",
    963     ),
    964     (
    965         "admit_signed_update",
    966         "social.post.verify_and_admit_event.valid",
    967     ),
    968     (
    969         "admit_signed_structural_photo",
    970         "social.post.verify_and_admit_event.valid",
    971     ),
    972     (
    973         "admit_signed_normalized_ask_precedes_malformed_media",
    974         "social.post.verify_and_admit_event.valid",
    975     ),
    976     (
    977         "admit_signed_thread_candidate_precedes_ask_and_media",
    978         "social.post.verify_and_admit_event.valid",
    979     ),
    980     (
    981         "admit_signed_empty_e_thread_candidate",
    982         "social.post.verify_and_admit_event.valid",
    983     ),
    984     (
    985         "admit_signed_empty_e_value_thread_candidate",
    986         "social.post.verify_and_admit_event.valid",
    987     ),
    988     (
    989         "admit_signed_duplicate_normalized_ask_marker",
    990         "social.post.verify_and_admit_event.invalid",
    991     ),
    992     (
    993         "admit_signed_kind_20_is_not_photo_update",
    994         "social.post.verify_and_admit_event.invalid",
    995     ),
    996     (
    997         "admit_signed_invalid_signature",
    998         "social.post.verify_and_admit_event.invalid",
    999     ),
   1000 ];
   1001 const FOOD_AVAILABILITY_OPERATION_EXPECTATIONS: [FoodAvailabilityOperationExpectation; 4] = [
   1002     FoodAvailabilityOperationExpectation {
   1003         key: "food_availability_build_authored_draft",
   1004         id: "food_availability.build_authored_draft",
   1005         inputs: &["FoodAvailabilityDetails", "u64"],
   1006         outputs: &["Nip01EventWireParts"],
   1007         error_class: "encode_error",
   1008         signing: "none",
   1009         rust_modules: &[
   1010             "crates/event/src/food_availability.rs",
   1011             "crates/event_codec/src/food_availability/authored.rs",
   1012         ],
   1013         rust_types: &[
   1014             "radroots_blossom::ByteVerifiedDescriptor",
   1015             "radroots_event::food::availability::FoodAvailabilityDetails",
   1016             "radroots_event::food::availability::FoodAvailabilityDetailsParts",
   1017             "radroots_event::food::availability::FoodAvailabilityError",
   1018             "radroots_event::food::availability::FoodAvailabilityImage",
   1019             "radroots_event::media::AuthoredImage",
   1020             "radroots_event::wire::Nip01EventWireParts",
   1021             "radroots_event_codec::food_availability::authored::RadrootsFoodAvailabilityEncodeError",
   1022         ],
   1023         case_kinds: &[
   1024             "food_availability.build_authored_draft.valid",
   1025             "food_availability.build_authored_draft.invalid",
   1026         ],
   1027     },
   1028     FoodAvailabilityOperationExpectation {
   1029         key: "food_availability_project_verified_event",
   1030         id: "food_availability.project_verified_event",
   1031         inputs: &["RadrootsSignatureVerifiedEvent"],
   1032         outputs: &["RadrootsFoodAvailabilityProjectionOutcome"],
   1033         error_class: "parse_error",
   1034         signing: "none",
   1035         rust_modules: &[
   1036             "crates/event/src/classified_listing.rs",
   1037             "crates/event/src/food_availability.rs",
   1038             "crates/event_codec/src/food_availability/inbound.rs",
   1039         ],
   1040         rust_types: &[
   1041             "radroots_event::listing::classified::ClassifiedListingPartition",
   1042             "radroots_event::food::availability::FoodAvailabilityError",
   1043             "radroots_event_codec::food_availability::inbound::RadrootsFoodAvailabilityImageDiagnostic",
   1044             "radroots_event_codec::food_availability::inbound::RadrootsFoodAvailabilityProjectionError",
   1045             "radroots_event_codec::food_availability::inbound::RadrootsFoodAvailabilityProjectionOutcome",
   1046             "radroots_event_codec::food_availability::inbound::RadrootsInboundFoodAvailabilityImage",
   1047             "radroots_event_codec::food_availability::inbound::RadrootsInboundFoodAvailabilityProjection",
   1048             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
   1049         ],
   1050         case_kinds: &[
   1051             "food_availability.project_verified_event.valid",
   1052             "food_availability.project_verified_event.invalid",
   1053         ],
   1054     },
   1055     FoodAvailabilityOperationExpectation {
   1056         key: "food_availability_verify_and_admit_event",
   1057         id: "food_availability.verify_and_admit_event",
   1058         inputs: &["EventEnvelope"],
   1059         outputs: &["RadrootsFoodAvailabilityAdmissionOutcome"],
   1060         error_class: "admission_error",
   1061         signing: "nip01",
   1062         rust_modules: &[
   1063             "crates/event_codec/src/food_availability/admission.rs",
   1064             "crates/event_codec/src/food_availability/inbound.rs",
   1065             "crates/event_codec/src/verification.rs",
   1066         ],
   1067         rust_types: &[
   1068             "radroots_event::envelope::EventEnvelope",
   1069             "radroots_event_codec::food_availability::admission::RadrootsAdmittedFoodAvailabilityEvent",
   1070             "radroots_event_codec::food_availability::admission::RadrootsExcludedClassifiedListingCandidate",
   1071             "radroots_event_codec::food_availability::admission::RadrootsFoodAvailabilityAdmissionError",
   1072             "radroots_event_codec::food_availability::admission::RadrootsFoodAvailabilityAdmissionOutcome",
   1073             "radroots_event_codec::food_availability::inbound::RadrootsInboundFoodAvailabilityProjection",
   1074             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
   1075         ],
   1076         case_kinds: &[
   1077             "food_availability.verify_and_admit_event.valid",
   1078             "food_availability.verify_and_admit_event.invalid",
   1079         ],
   1080     },
   1081     FoodAvailabilityOperationExpectation {
   1082         key: "food_availability_validate_revision",
   1083         id: "food_availability.validate_revision",
   1084         inputs: &["RadrootsSignatureVerifiedEvent"],
   1085         outputs: &["Unit"],
   1086         error_class: "validation_error",
   1087         signing: "none",
   1088         rust_modules: &[
   1089             "crates/event_codec/src/food_availability/inbound.rs",
   1090             "crates/event_codec/src/food_availability/revision.rs",
   1091         ],
   1092         rust_types: &[
   1093             "radroots_event_codec::food_availability::inbound::RadrootsFoodAvailabilityProjectionError",
   1094             "radroots_event_codec::food_availability::revision::RadrootsFoodAvailabilityRevisionError",
   1095             "radroots_event_codec::verify::RadrootsSignatureVerifiedEvent",
   1096         ],
   1097         case_kinds: &[
   1098             "food_availability.validate_revision.valid",
   1099             "food_availability.validate_revision.invalid",
   1100         ],
   1101     },
   1102 ];
   1103 const FOOD_AVAILABILITY_CASE_KINDS: [&str; 8] = [
   1104     "food_availability.build_authored_draft.valid",
   1105     "food_availability.build_authored_draft.invalid",
   1106     "food_availability.project_verified_event.valid",
   1107     "food_availability.project_verified_event.invalid",
   1108     "food_availability.verify_and_admit_event.valid",
   1109     "food_availability.verify_and_admit_event.invalid",
   1110     "food_availability.validate_revision.valid",
   1111     "food_availability.validate_revision.invalid",
   1112 ];
   1113 const FOOD_AVAILABILITY_VECTOR_EXPECTATIONS: [(&str, &str); 40] = [
   1114     (
   1115         "food_authored_unit_g_001",
   1116         "food_availability.build_authored_draft.valid",
   1117     ),
   1118     (
   1119         "food_authored_unit_kg_002",
   1120         "food_availability.build_authored_draft.valid",
   1121     ),
   1122     (
   1123         "food_authored_unit_lb_003",
   1124         "food_availability.build_authored_draft.valid",
   1125     ),
   1126     (
   1127         "food_authored_unit_oz_004",
   1128         "food_availability.build_authored_draft.valid",
   1129     ),
   1130     (
   1131         "food_authored_unit_each_005",
   1132         "food_availability.build_authored_draft.valid",
   1133     ),
   1134     (
   1135         "food_authored_unit_dozen_006",
   1136         "food_availability.build_authored_draft.valid",
   1137     ),
   1138     (
   1139         "food_authored_unit_bunch_007",
   1140         "food_availability.build_authored_draft.valid",
   1141     ),
   1142     (
   1143         "food_authored_unit_punnet_008",
   1144         "food_availability.build_authored_draft.valid",
   1145     ),
   1146     (
   1147         "food_authored_unit_bag_009",
   1148         "food_availability.build_authored_draft.valid",
   1149     ),
   1150     (
   1151         "food_authored_unit_basket_010",
   1152         "food_availability.build_authored_draft.valid",
   1153     ),
   1154     (
   1155         "food_authored_wire_budget_ascii_max_011",
   1156         "food_availability.build_authored_draft.valid",
   1157     ),
   1158     (
   1159         "food_authored_wire_budget_escaped_overflow_012",
   1160         "food_availability.build_authored_draft.invalid",
   1161     ),
   1162     (
   1163         "food_authored_future_published_at_013",
   1164         "food_availability.build_authored_draft.invalid",
   1165     ),
   1166     (
   1167         "food_admission_normalizes_decimal_currency_014",
   1168         "food_availability.project_verified_event.valid",
   1169     ),
   1170     (
   1171         "food_admission_optional_standard_tags_015",
   1172         "food_availability.verify_and_admit_event.valid",
   1173     ),
   1174     (
   1175         "food_admission_excludes_operational_before_validation_016",
   1176         "food_availability.project_verified_event.valid",
   1177     ),
   1178     (
   1179         "food_admission_excludes_generic_nip99_017",
   1180         "food_availability.project_verified_event.valid",
   1181     ),
   1182     (
   1183         "food_admission_rejects_ambiguous_markers_018",
   1184         "food_availability.project_verified_event.invalid",
   1185     ),
   1186     (
   1187         "food_admission_rejects_wrong_kind_019",
   1188         "food_availability.project_verified_event.invalid",
   1189     ),
   1190     (
   1191         "food_admission_rejects_core_tag_shape_020",
   1192         "food_availability.project_verified_event.invalid",
   1193     ),
   1194     (
   1195         "food_admission_rejects_prohibited_delivery_021",
   1196         "food_availability.project_verified_event.invalid",
   1197     ),
   1198     (
   1199         "food_admission_rejects_price_frequency_022",
   1200         "food_availability.project_verified_event.invalid",
   1201     ),
   1202     (
   1203         "food_admission_requires_price_unit_023",
   1204         "food_availability.project_verified_event.invalid",
   1205     ),
   1206     (
   1207         "food_admission_bounds_raw_decimal_digits_024",
   1208         "food_availability.project_verified_event.invalid",
   1209     ),
   1210     (
   1211         "food_admission_rejects_malformed_price_unit_025",
   1212         "food_availability.project_verified_event.invalid",
   1213     ),
   1214     (
   1215         "food_admission_rejects_quantity_unit_mismatch_026",
   1216         "food_availability.project_verified_event.invalid",
   1217     ),
   1218     (
   1219         "food_admission_rejects_status_027",
   1220         "food_availability.project_verified_event.invalid",
   1221     ),
   1222     (
   1223         "food_admission_rejects_future_published_at_028",
   1224         "food_availability.project_verified_event.invalid",
   1225     ),
   1226     (
   1227         "food_admission_preserves_ordered_image_diagnostics_029",
   1228         "food_availability.project_verified_event.valid",
   1229     ),
   1230     (
   1231         "food_admission_bounds_image_projection_030",
   1232         "food_availability.project_verified_event.valid",
   1233     ),
   1234     (
   1235         "food_admission_rejects_invalid_signature_031",
   1236         "food_availability.verify_and_admit_event.invalid",
   1237     ),
   1238     (
   1239         "food_revision_accepts_later_created_at_032",
   1240         "food_availability.validate_revision.valid",
   1241     ),
   1242     (
   1243         "food_revision_rejects_invalid_previous_033",
   1244         "food_availability.validate_revision.invalid",
   1245     ),
   1246     (
   1247         "food_revision_rejects_invalid_current_034",
   1248         "food_availability.validate_revision.invalid",
   1249     ),
   1250     (
   1251         "food_revision_rejects_identifier_coordinate_change_035",
   1252         "food_availability.validate_revision.invalid",
   1253     ),
   1254     (
   1255         "food_revision_rejects_author_coordinate_change_036",
   1256         "food_availability.validate_revision.invalid",
   1257     ),
   1258     (
   1259         "food_revision_rejects_published_at_change_037",
   1260         "food_availability.validate_revision.invalid",
   1261     ),
   1262     (
   1263         "food_revision_rejects_older_created_at_038",
   1264         "food_availability.validate_revision.invalid",
   1265     ),
   1266     (
   1267         "food_revision_equal_time_a_current_039",
   1268         "food_availability.validate_revision.invalid",
   1269     ),
   1270     (
   1271         "food_revision_equal_time_b_current_040",
   1272         "food_availability.validate_revision.valid",
   1273     ),
   1274 ];
   1275 #[derive(Debug, Deserialize)]
   1276 #[serde(deny_unknown_fields)]
   1277 pub struct ContractManifest {
   1278     pub contract: ManifestContract,
   1279     pub surface: Surface,
   1280     pub policy: Policy,
   1281 }
   1282 
   1283 #[derive(Debug, Deserialize)]
   1284 #[serde(deny_unknown_fields)]
   1285 pub struct ManifestContract {
   1286     pub name: String,
   1287     pub version: String,
   1288     pub source: String,
   1289 }
   1290 
   1291 #[derive(Debug, Deserialize)]
   1292 #[serde(deny_unknown_fields)]
   1293 pub struct Surface {
   1294     pub model_crates: Vec<String>,
   1295     pub algorithm_crates: Vec<String>,
   1296     pub rust_crate_tiers: Option<RustCrateTiers>,
   1297     pub internal_replica_crates: Option<InternalReplicaCrates>,
   1298 }
   1299 
   1300 #[derive(Debug, Deserialize)]
   1301 #[serde(deny_unknown_fields)]
   1302 pub struct RustCrateTiers {
   1303     pub advanced_substrate: Vec<String>,
   1304     pub published_support: Vec<String>,
   1305     pub deferred_publication: Vec<String>,
   1306 }
   1307 
   1308 #[derive(Debug, Deserialize)]
   1309 #[serde(deny_unknown_fields)]
   1310 pub struct InternalReplicaCrates {
   1311     pub schema: String,
   1312     pub storage: String,
   1313     pub sync: String,
   1314 }
   1315 
   1316 #[derive(Debug, Deserialize)]
   1317 #[serde(deny_unknown_fields)]
   1318 pub struct Policy {
   1319     pub exclude_internal_workspace_crates: bool,
   1320     pub require_reproducible_exports: bool,
   1321     pub require_conformance_vectors: bool,
   1322     pub replica: Option<ReplicaPolicy>,
   1323 }
   1324 
   1325 #[derive(Debug, Deserialize)]
   1326 #[serde(deny_unknown_fields)]
   1327 pub struct ReplicaPolicy {
   1328     pub forbid_legacy_alias_identifiers: bool,
   1329     pub require_transport_agnostic_sync_contract: bool,
   1330     pub require_deterministic_emit_ingest: bool,
   1331 }
   1332 
   1333 #[derive(Debug, Deserialize)]
   1334 #[serde(deny_unknown_fields)]
   1335 pub struct ReplicaContractManifest {
   1336     pub schema_version: u32,
   1337     pub contract: ReplicaContractMetadata,
   1338     pub crate_family: ReplicaContractCrateFamily,
   1339     pub policy: ReplicaContractPolicy,
   1340     pub transfer: ReplicaTransferContract,
   1341 }
   1342 
   1343 #[derive(Debug, Deserialize)]
   1344 #[serde(deny_unknown_fields)]
   1345 pub struct ReplicaContractMetadata {
   1346     pub name: String,
   1347     pub version: String,
   1348     pub purpose: String,
   1349 }
   1350 
   1351 #[derive(Debug, Deserialize)]
   1352 #[serde(deny_unknown_fields)]
   1353 pub struct ReplicaContractCrateFamily {
   1354     pub schema: String,
   1355     pub storage: String,
   1356     pub sync: String,
   1357 }
   1358 
   1359 #[derive(Debug, Deserialize)]
   1360 #[serde(deny_unknown_fields)]
   1361 pub struct ReplicaContractPolicy {
   1362     pub transport_agnostic_sync_core: bool,
   1363     pub deterministic_emit_and_ingest: bool,
   1364     pub forbid_legacy_alias_identifiers: bool,
   1365     pub profile_event_emission: String,
   1366     pub unknown_sync_request_fields: String,
   1367     pub classified_listing_signature_verification: String,
   1368     pub classified_listing_head_selection: String,
   1369     pub classified_listing_operational_projection: String,
   1370     pub classified_listing_excluded_or_rejected_head: String,
   1371     pub classified_listing_head_only_ingest: String,
   1372     pub legacy_bare_envelope_ingest: String,
   1373     pub legacy_ingest_feature: String,
   1374     pub phase_1_ingest_replacement: String,
   1375     pub future_product_ingest_input: String,
   1376 }
   1377 
   1378 #[derive(Debug, Deserialize)]
   1379 #[serde(deny_unknown_fields)]
   1380 pub struct ReplicaTransferContract {
   1381     pub version: u32,
   1382     pub source: String,
   1383     pub constant: String,
   1384 }
   1385 
   1386 #[derive(Debug, Deserialize)]
   1387 #[serde(deny_unknown_fields)]
   1388 pub struct OperationsContractManifest {
   1389     pub contract: ManifestContract,
   1390     pub public: PublicContract,
   1391     pub shared_types: SharedTypesContract,
   1392     pub errors: ErrorClassesContract,
   1393     pub operations: BTreeMap<String, PublicOperationContract>,
   1394     pub implementation_provenance: Option<ImplementationProvenance>,
   1395 }
   1396 
   1397 #[derive(Debug, Deserialize)]
   1398 #[serde(deny_unknown_fields)]
   1399 pub struct PublicContract {
   1400     pub domains: Vec<String>,
   1401 }
   1402 
   1403 #[derive(Debug, Deserialize)]
   1404 #[serde(deny_unknown_fields)]
   1405 pub struct SharedTypesContract {
   1406     pub public: Vec<String>,
   1407 }
   1408 
   1409 #[derive(Debug, Deserialize)]
   1410 #[serde(deny_unknown_fields)]
   1411 pub struct ErrorClassesContract {
   1412     pub classes: Vec<String>,
   1413 }
   1414 
   1415 #[derive(Debug, Deserialize)]
   1416 #[serde(deny_unknown_fields)]
   1417 pub struct ImplementationProvenance {
   1418     pub model_crates: Vec<String>,
   1419     pub algorithm_crates: Vec<String>,
   1420 }
   1421 
   1422 #[derive(Debug, Deserialize)]
   1423 #[serde(deny_unknown_fields)]
   1424 pub struct PublicOperationContract {
   1425     pub domain: String,
   1426     pub id: String,
   1427     pub stability: String,
   1428     pub inputs: Vec<String>,
   1429     pub outputs: Vec<String>,
   1430     pub error_class: String,
   1431     #[allow(dead_code)]
   1432     pub deterministic: bool,
   1433     pub signing: String,
   1434     pub transport: String,
   1435     pub implementation: PublicOperationImplementation,
   1436     pub conformance: PublicOperationConformance,
   1437 }
   1438 
   1439 #[derive(Debug, Deserialize)]
   1440 #[serde(deny_unknown_fields)]
   1441 pub struct PublicOperationImplementation {
   1442     pub rust_modules: Vec<String>,
   1443     pub rust_types: Vec<String>,
   1444 }
   1445 
   1446 #[derive(Debug, Deserialize)]
   1447 #[serde(deny_unknown_fields)]
   1448 pub struct PublicOperationConformance {
   1449     pub vector: String,
   1450     #[serde(default)]
   1451     pub case_kinds: Vec<String>,
   1452 }
   1453 
   1454 #[derive(Debug, Deserialize, Serialize)]
   1455 #[serde(deny_unknown_fields)]
   1456 struct DeletionConformanceRawEvent {
   1457     id: String,
   1458     pubkey: String,
   1459     created_at: u64,
   1460     kind: u32,
   1461     tags: Vec<Vec<String>>,
   1462     content: String,
   1463     sig: String,
   1464 }
   1465 
   1466 #[derive(Clone, Copy)]
   1467 struct CalendarOperationExpectation {
   1468     key: &'static str,
   1469     id: &'static str,
   1470     inputs: &'static [&'static str],
   1471     outputs: &'static [&'static str],
   1472     error_class: &'static str,
   1473     rust_modules: &'static [&'static str],
   1474     rust_types: &'static [&'static str],
   1475     vector: &'static str,
   1476 }
   1477 
   1478 #[derive(Clone, Copy)]
   1479 struct PostOperationExpectation {
   1480     key: &'static str,
   1481     id: &'static str,
   1482     inputs: &'static [&'static str],
   1483     outputs: &'static [&'static str],
   1484     error_class: &'static str,
   1485     signing: &'static str,
   1486     rust_modules: &'static [&'static str],
   1487     rust_types: &'static [&'static str],
   1488     case_kinds: &'static [&'static str],
   1489 }
   1490 
   1491 #[derive(Clone, Copy)]
   1492 struct CommentOperationExpectation {
   1493     key: &'static str,
   1494     id: &'static str,
   1495     inputs: &'static [&'static str],
   1496     outputs: &'static [&'static str],
   1497     error_class: &'static str,
   1498     signing: &'static str,
   1499     rust_modules: &'static [&'static str],
   1500     rust_types: &'static [&'static str],
   1501     case_kinds: &'static [&'static str],
   1502 }
   1503 
   1504 #[derive(Clone, Copy)]
   1505 struct DeletionOperationExpectation {
   1506     key: &'static str,
   1507     id: &'static str,
   1508     vector: &'static str,
   1509     inputs: &'static [&'static str],
   1510     outputs: &'static [&'static str],
   1511     error_class: &'static str,
   1512     signing: &'static str,
   1513     rust_modules: &'static [&'static str],
   1514     rust_types: &'static [&'static str],
   1515     case_kinds: &'static [&'static str],
   1516 }
   1517 
   1518 #[derive(Clone, Copy)]
   1519 struct FoodAvailabilityOperationExpectation {
   1520     key: &'static str,
   1521     id: &'static str,
   1522     inputs: &'static [&'static str],
   1523     outputs: &'static [&'static str],
   1524     error_class: &'static str,
   1525     signing: &'static str,
   1526     rust_modules: &'static [&'static str],
   1527     rust_types: &'static [&'static str],
   1528     case_kinds: &'static [&'static str],
   1529 }
   1530 
   1531 #[derive(Debug, Deserialize)]
   1532 #[serde(deny_unknown_fields)]
   1533 pub struct VersionPolicy {
   1534     pub contract: VersionContract,
   1535     pub semver: SemverRules,
   1536     pub release_integrity: ReleaseIntegrityRules,
   1537 }
   1538 
   1539 #[derive(Debug, Deserialize)]
   1540 #[serde(deny_unknown_fields)]
   1541 pub struct VersionContract {
   1542     pub version: String,
   1543     pub stability: String,
   1544 }
   1545 
   1546 #[derive(Debug, Deserialize)]
   1547 #[serde(deny_unknown_fields)]
   1548 pub struct SemverRules {
   1549     pub major_on: Vec<String>,
   1550     pub minor_on: Vec<String>,
   1551     pub patch_on: Vec<String>,
   1552 }
   1553 
   1554 #[derive(Debug, Deserialize)]
   1555 #[serde(deny_unknown_fields)]
   1556 pub struct ReleaseIntegrityRules {
   1557     pub requires_conformance_pass: bool,
   1558     pub requires_contract_manifest_diff: bool,
   1559     pub requires_release_notes: bool,
   1560 }
   1561 
   1562 #[derive(Debug, Deserialize)]
   1563 #[serde(deny_unknown_fields)]
   1564 struct ReleaseRecord {
   1565     schema_version: u32,
   1566     release: ReleaseRecordMetadata,
   1567     artifacts: ReleaseRecordArtifacts,
   1568     changes: Vec<ReleaseRecordChange>,
   1569 }
   1570 
   1571 #[derive(Debug, Deserialize)]
   1572 #[serde(deny_unknown_fields)]
   1573 struct ReleaseRecordMetadata {
   1574     version: String,
   1575     previous_version: String,
   1576     contract_base_version: String,
   1577     status: String,
   1578 }
   1579 
   1580 #[derive(Debug, Deserialize)]
   1581 #[serde(deny_unknown_fields)]
   1582 struct ReleaseRecordArtifacts {
   1583     changelog: String,
   1584     manifest: String,
   1585     operations: String,
   1586     replica: String,
   1587     conformance: String,
   1588     publish_policy: String,
   1589     #[serde(default)]
   1590     sqlite_runtime: Option<String>,
   1591 }
   1592 
   1593 #[derive(Debug, Deserialize)]
   1594 #[serde(deny_unknown_fields)]
   1595 struct SqliteRuntimeContract {
   1596     schema_version: u32,
   1597     package: SqliteRuntimePackage,
   1598     activation: SqliteRuntimeActivation,
   1599     access: SqliteRuntimeAccess,
   1600     sealed_native_adapter: SqliteRuntimeSealedNativeAdapter,
   1601     migration: SqliteRuntimeMigration,
   1602 }
   1603 
   1604 #[derive(Debug, Deserialize)]
   1605 #[serde(deny_unknown_fields)]
   1606 struct SqliteRuntimePackage {
   1607     name: String,
   1608     version: String,
   1609     source: String,
   1610     checksum: String,
   1611 }
   1612 
   1613 #[derive(Debug, Deserialize)]
   1614 #[serde(deny_unknown_fields)]
   1615 struct SqliteRuntimeActivation {
   1616     route: Vec<String>,
   1617 }
   1618 
   1619 #[derive(Debug, Deserialize)]
   1620 #[serde(deny_unknown_fields)]
   1621 struct SqliteRuntimeAccess {
   1622     high_level_library: String,
   1623     native_linkage_owner: String,
   1624     native_linkage_package: String,
   1625     maximum_native_linkages: u32,
   1626     forbidden_high_level_dependencies: Vec<String>,
   1627 }
   1628 
   1629 #[derive(Debug, Deserialize)]
   1630 #[serde(deny_unknown_fields)]
   1631 struct SqliteRuntimeSealedNativeAdapter {
   1632     owner_package: String,
   1633     relative_module: String,
   1634     capability: String,
   1635     status: String,
   1636 }
   1637 
   1638 #[derive(Debug, Deserialize)]
   1639 #[serde(deny_unknown_fields)]
   1640 struct SqliteRuntimeMigration {
   1641     owner: String,
   1642     status: String,
   1643     temporary_direct_dependencies: Vec<String>,
   1644 }
   1645 
   1646 #[derive(Debug, Deserialize)]
   1647 #[serde(deny_unknown_fields)]
   1648 struct ReleaseRecordChange {
   1649     id: String,
   1650     classification: String,
   1651     semver_impacts: Vec<String>,
   1652     summary: String,
   1653 }
   1654 
   1655 #[derive(Debug)]
   1656 pub struct ContractBundle {
   1657     pub root: PathBuf,
   1658     pub manifest: ContractManifest,
   1659     pub version: VersionPolicy,
   1660     pub replica: ReplicaContractManifest,
   1661     pub operations_manifest: OperationsContractManifest,
   1662 }
   1663 
   1664 #[derive(Debug, Deserialize)]
   1665 struct WorkspaceCargoManifest {
   1666     workspace: WorkspaceSection,
   1667 }
   1668 
   1669 #[derive(Debug, Deserialize)]
   1670 struct WorkspaceSection {
   1671     members: Vec<String>,
   1672 }
   1673 
   1674 #[derive(Debug, Deserialize)]
   1675 struct WorkspaceVersionCargoManifest {
   1676     workspace: WorkspaceVersionSection,
   1677 }
   1678 
   1679 #[derive(Debug, Deserialize)]
   1680 struct WorkspaceVersionSection {
   1681     members: Vec<String>,
   1682     package: WorkspacePackageVersion,
   1683     dependencies: BTreeMap<String, WorkspaceDependencyVersion>,
   1684 }
   1685 
   1686 #[derive(Debug, Deserialize)]
   1687 struct WorkspacePackageVersion {
   1688     version: String,
   1689     #[serde(default)]
   1690     repository: String,
   1691 }
   1692 
   1693 #[derive(Debug, Deserialize)]
   1694 struct WorkspaceDependencyVersion {
   1695     path: Option<String>,
   1696     version: Option<String>,
   1697 }
   1698 
   1699 #[derive(Debug, Deserialize)]
   1700 struct VersionedPackageCargoManifest {
   1701     package: VersionedPackageSection,
   1702 }
   1703 
   1704 #[derive(Debug, Deserialize)]
   1705 struct VersionedPackageSection {
   1706     name: String,
   1707     version: PackageVersionSource,
   1708 }
   1709 
   1710 #[derive(Debug, Deserialize)]
   1711 #[serde(untagged)]
   1712 enum PackageVersionSource {
   1713     Literal(String),
   1714     Workspace { workspace: bool },
   1715 }
   1716 
   1717 #[derive(Debug, Deserialize)]
   1718 struct CargoLockManifest {
   1719     package: Vec<CargoLockPackage>,
   1720 }
   1721 
   1722 #[derive(Debug, Deserialize)]
   1723 struct CargoLockPackage {
   1724     name: String,
   1725     version: String,
   1726     source: Option<String>,
   1727     checksum: Option<String>,
   1728 }
   1729 
   1730 #[derive(Debug, Deserialize)]
   1731 struct PackageCargoManifest {
   1732     package: PackageSection,
   1733 }
   1734 
   1735 #[derive(Debug, Deserialize)]
   1736 struct PackageSection {
   1737     name: String,
   1738     publish: Option<PackagePublish>,
   1739 }
   1740 
   1741 #[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
   1742 #[serde(untagged)]
   1743 enum PackagePublish {
   1744     Bool(bool),
   1745     Registries(Vec<String>),
   1746 }
   1747 
   1748 #[cfg_attr(not(test), allow(dead_code))]
   1749 #[derive(Debug, Deserialize)]
   1750 struct CoverageRequiredFile {
   1751     required: CoverageRequiredSection,
   1752 }
   1753 
   1754 #[cfg_attr(not(test), allow(dead_code))]
   1755 #[derive(Debug, Deserialize)]
   1756 struct CoverageRequiredSection {
   1757     crates: Vec<String>,
   1758 }
   1759 
   1760 #[derive(Debug, Clone, PartialEq, Eq)]
   1761 struct EventBoundaryRow {
   1762     domain: String,
   1763     kind: String,
   1764     radroots_type: String,
   1765     rpc_methods: BTreeSet<String>,
   1766 }
   1767 
   1768 #[derive(Clone, Copy)]
   1769 struct EventBoundarySourceWitness {
   1770     relative_path: &'static str,
   1771     required_fragments: &'static [&'static str],
   1772 }
   1773 
   1774 #[derive(Clone, Copy)]
   1775 struct EventBoundaryExpectation {
   1776     domain: &'static str,
   1777     kind: &'static str,
   1778     radroots_type: &'static str,
   1779     rpc_methods: &'static [&'static str],
   1780     witnesses: &'static [EventBoundarySourceWitness],
   1781 }
   1782 
   1783 const PROFILE_WITNESSES: [EventBoundarySourceWitness; 5] = [
   1784     EventBoundarySourceWitness {
   1785         relative_path: "crates/event/src/profile.rs",
   1786         required_fragments: &["pub struct AuthoredProfile"],
   1787     },
   1788     EventBoundarySourceWitness {
   1789         relative_path: "crates/event_codec/src/profile/inbound/registry_v7.rs",
   1790         required_fragments: &["pub struct RadrootsInboundProfileMetadata"],
   1791     },
   1792     EventBoundarySourceWitness {
   1793         relative_path: "crates/event_codec/src/profile/admission.rs",
   1794         required_fragments: &[
   1795             "pub struct RadrootsAdmittedProfileEvent",
   1796             "pub fn verify_and_admit_profile_event",
   1797         ],
   1798     },
   1799     EventBoundarySourceWitness {
   1800         relative_path: "crates/event_codec/src/verification/v1.rs",
   1801         required_fragments: &[
   1802             "pub struct RadrootsSignatureVerifiedEvent",
   1803             "pub fn verify_nip01_event",
   1804         ],
   1805     },
   1806     EventBoundarySourceWitness {
   1807         relative_path: "crates/event/src/kinds.rs",
   1808         required_fragments: &["pub const KIND_PROFILE: u32 = 0;"],
   1809     },
   1810 ];
   1811 
   1812 const FOLLOW_WITNESSES: [EventBoundarySourceWitness; 2] = [
   1813     EventBoundarySourceWitness {
   1814         relative_path: "crates/event/src/follow.rs",
   1815         required_fragments: &["pub struct Follow"],
   1816     },
   1817     EventBoundarySourceWitness {
   1818         relative_path: "crates/event/src/kinds.rs",
   1819         required_fragments: &["pub const KIND_FOLLOW: u32 = 3;"],
   1820     },
   1821 ];
   1822 
   1823 const POST_WITNESSES: [EventBoundarySourceWitness; 5] = [
   1824     EventBoundarySourceWitness {
   1825         relative_path: "crates/event/src/post.rs",
   1826         required_fragments: &[
   1827             "pub struct Post",
   1828             "pub struct AuthoredUpdate",
   1829             "pub struct AuthoredPhotoUpdate",
   1830             "pub struct AuthoredAsk",
   1831         ],
   1832     },
   1833     EventBoundarySourceWitness {
   1834         relative_path: "crates/event_codec/src/post/authored.rs",
   1835         required_fragments: &[
   1836             "pub fn authored_update_to_wire_parts",
   1837             "pub fn authored_photo_update_to_wire_parts",
   1838             "pub fn authored_ask_to_wire_parts",
   1839         ],
   1840     },
   1841     EventBoundarySourceWitness {
   1842         relative_path: "crates/event_codec/src/post/inbound/registry_v7.rs",
   1843         required_fragments: &[
   1844             "pub struct RadrootsInboundPostProjection",
   1845             "pub fn project_verified_post_event",
   1846         ],
   1847     },
   1848     EventBoundarySourceWitness {
   1849         relative_path: "crates/event_codec/src/post/admission.rs",
   1850         required_fragments: &[
   1851             "pub struct RadrootsAdmittedRootPostEvent",
   1852             "pub struct RadrootsThreadExcludedPostCandidate",
   1853             "pub enum RadrootsPostAdmissionOutcome",
   1854             "pub fn verify_and_admit_post_event",
   1855         ],
   1856     },
   1857     EventBoundarySourceWitness {
   1858         relative_path: "crates/event/src/kinds.rs",
   1859         required_fragments: &["pub const KIND_POST: u32 = 1;"],
   1860     },
   1861 ];
   1862 
   1863 const REPLY_WITNESSES: [EventBoundarySourceWitness; 5] = [
   1864     EventBoundarySourceWitness {
   1865         relative_path: "crates/event/src/relay_hint.rs",
   1866         required_fragments: &["pub struct NostrRelayHint"],
   1867     },
   1868     EventBoundarySourceWitness {
   1869         relative_path: "crates/event/src/reply.rs",
   1870         required_fragments: &[
   1871             "pub struct Nip10ReplyReference",
   1872             "pub struct AuthoredNip10Reply",
   1873         ],
   1874     },
   1875     EventBoundarySourceWitness {
   1876         relative_path: "crates/event_codec/src/reply/inbound/registry_v7.rs",
   1877         required_fragments: &[
   1878             "pub struct RadrootsInboundNip10ReplyProjection",
   1879             "pub fn project_verified_nip10_reply_event",
   1880         ],
   1881     },
   1882     EventBoundarySourceWitness {
   1883         relative_path: "crates/event_codec/src/reply/admission.rs",
   1884         required_fragments: &[
   1885             "pub struct RadrootsAdmittedNip10ReplyEvent",
   1886             "pub fn verify_and_admit_nip10_reply_event",
   1887         ],
   1888     },
   1889     EventBoundarySourceWitness {
   1890         relative_path: "crates/nostr/src/events/reply.rs",
   1891         required_fragments: &[
   1892             "pub struct Nip10ReplyBuilder",
   1893             "pub fn build_nip10_reply_event",
   1894         ],
   1895     },
   1896 ];
   1897 
   1898 const COMMENT_WITNESSES: [EventBoundarySourceWitness; 7] = [
   1899     EventBoundarySourceWitness {
   1900         relative_path: "crates/event/src/relay_hint.rs",
   1901         required_fragments: &["pub struct NostrRelayHint"],
   1902     },
   1903     EventBoundarySourceWitness {
   1904         relative_path: "crates/event/src/comment.rs",
   1905         required_fragments: &[
   1906             "pub enum Nip22CommentRoot",
   1907             "pub enum Nip22CommentPosition",
   1908             "pub struct AuthoredNip22Comment",
   1909         ],
   1910     },
   1911     EventBoundarySourceWitness {
   1912         relative_path: "crates/event_codec/src/comment/authored.rs",
   1913         required_fragments: &["pub fn authored_nip22_comment_to_wire_parts"],
   1914     },
   1915     EventBoundarySourceWitness {
   1916         relative_path: "crates/event_codec/src/comment/inbound/registry_v7.rs",
   1917         required_fragments: &[
   1918             "pub struct RadrootsInboundNip22CommentProjection",
   1919             "pub fn project_verified_nip22_comment_event",
   1920         ],
   1921     },
   1922     EventBoundarySourceWitness {
   1923         relative_path: "crates/event_codec/src/comment/admission.rs",
   1924         required_fragments: &[
   1925             "pub struct RadrootsAdmittedNip22CommentEvent",
   1926             "pub fn verify_and_admit_nip22_comment_event",
   1927         ],
   1928     },
   1929     EventBoundarySourceWitness {
   1930         relative_path: "crates/nostr/src/events/comment.rs",
   1931         required_fragments: &[
   1932             "pub struct Nip22CommentBuilder",
   1933             "pub fn build_nip22_comment_event",
   1934         ],
   1935     },
   1936     EventBoundarySourceWitness {
   1937         relative_path: "crates/event/src/kinds.rs",
   1938         required_fragments: &["pub const KIND_COMMENT: u32 = 1111;"],
   1939     },
   1940 ];
   1941 
   1942 const DELETION_WITNESSES: [EventBoundarySourceWitness; 7] = [
   1943     EventBoundarySourceWitness {
   1944         relative_path: "crates/event/src/deletion.rs",
   1945         required_fragments: &["pub struct AuthoredNip09DeletionRequest"],
   1946     },
   1947     EventBoundarySourceWitness {
   1948         relative_path: "crates/event_codec/src/deletion/authored.rs",
   1949         required_fragments: &["pub fn authored_nip09_deletion_request_to_wire_parts"],
   1950     },
   1951     EventBoundarySourceWitness {
   1952         relative_path: "crates/event_codec/src/deletion/reconciliation_v1.rs",
   1953         required_fragments: &[
   1954             "pub struct RadrootsInboundNip09DeletionProjection",
   1955             "pub fn project_verified_nip09_deletion_request_event",
   1956         ],
   1957     },
   1958     EventBoundarySourceWitness {
   1959         relative_path: "crates/event_codec/src/deletion/reconciliation_v1.rs",
   1960         required_fragments: &[
   1961             "pub struct RadrootsAdmittedNip09DeletionRequestEvent",
   1962             "pub fn verify_and_admit_nip09_deletion_request_event",
   1963         ],
   1964     },
   1965     EventBoundarySourceWitness {
   1966         relative_path: "crates/event_codec/src/deletion/reconciliation_v1.rs",
   1967         required_fragments: &[
   1968             "pub enum RadrootsNip09SuppressionOutcome",
   1969             "pub enum RadrootsNip09SuppressionReason",
   1970             "pub struct RadrootsNip09EventReferenceEvidence",
   1971             "pub struct RadrootsNip09AddressReferenceEvidence",
   1972             "pub struct RadrootsNip09SuppressionDecision",
   1973             "pub fn evaluate_nip09_suppression",
   1974         ],
   1975     },
   1976     EventBoundarySourceWitness {
   1977         relative_path: "crates/nostr/src/events/deletion.rs",
   1978         required_fragments: &[
   1979             "pub struct Nip09DeletionRequestBuilder",
   1980             "pub fn build_nip09_deletion_request_event",
   1981         ],
   1982     },
   1983     EventBoundarySourceWitness {
   1984         relative_path: "crates/event/src/kinds.rs",
   1985         required_fragments: &["pub const KIND_DELETION_REQUEST: u32 = 5;"],
   1986     },
   1987 ];
   1988 
   1989 const REACTION_WITNESSES: [EventBoundarySourceWitness; 2] = [
   1990     EventBoundarySourceWitness {
   1991         relative_path: "crates/event/src/reaction.rs",
   1992         required_fragments: &["pub struct Reaction"],
   1993     },
   1994     EventBoundarySourceWitness {
   1995         relative_path: "crates/event/src/kinds.rs",
   1996         required_fragments: &["pub const KIND_REACTION: u32 = 7;"],
   1997     },
   1998 ];
   1999 
   2000 const REPOST_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2001     EventBoundarySourceWitness {
   2002         relative_path: "crates/event/src/repost.rs",
   2003         required_fragments: &["pub struct Repost"],
   2004     },
   2005     EventBoundarySourceWitness {
   2006         relative_path: "crates/event/src/kinds.rs",
   2007         required_fragments: &["pub const KIND_REPOST: u32 = 6;"],
   2008     },
   2009 ];
   2010 
   2011 const GENERIC_REPOST_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2012     EventBoundarySourceWitness {
   2013         relative_path: "crates/event/src/repost.rs",
   2014         required_fragments: &["pub struct GenericRepost"],
   2015     },
   2016     EventBoundarySourceWitness {
   2017         relative_path: "crates/event/src/kinds.rs",
   2018         required_fragments: &["pub const KIND_GENERIC_REPOST: u32 = 16;"],
   2019     },
   2020 ];
   2021 
   2022 const SEAL_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2023     EventBoundarySourceWitness {
   2024         relative_path: "crates/event/src/seal.rs",
   2025         required_fragments: &["pub struct Seal"],
   2026     },
   2027     EventBoundarySourceWitness {
   2028         relative_path: "crates/event/src/kinds.rs",
   2029         required_fragments: &["pub const KIND_SEAL: u32 = 13;"],
   2030     },
   2031 ];
   2032 
   2033 const MESSAGE_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2034     EventBoundarySourceWitness {
   2035         relative_path: "crates/event/src/message.rs",
   2036         required_fragments: &["pub struct Message"],
   2037     },
   2038     EventBoundarySourceWitness {
   2039         relative_path: "crates/event/src/kinds.rs",
   2040         required_fragments: &["pub const KIND_MESSAGE: u32 = 14;"],
   2041     },
   2042     EventBoundarySourceWitness {
   2043         relative_path: "crates/nostr/src/nip17.rs",
   2044         required_fragments: &["pub async fn wrap_message<T>(", "KIND_MESSAGE =>"],
   2045     },
   2046     EventBoundarySourceWitness {
   2047         relative_path: "crates/nostr/src/lib.rs",
   2048         required_fragments: &["pub mod nip17;"],
   2049     },
   2050 ];
   2051 
   2052 const MESSAGE_FILE_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2053     EventBoundarySourceWitness {
   2054         relative_path: "crates/event/src/message_file.rs",
   2055         required_fragments: &["pub struct MessageFile"],
   2056     },
   2057     EventBoundarySourceWitness {
   2058         relative_path: "crates/event/src/kinds.rs",
   2059         required_fragments: &["pub const KIND_MESSAGE_FILE: u32 = 15;"],
   2060     },
   2061     EventBoundarySourceWitness {
   2062         relative_path: "crates/nostr/src/nip17.rs",
   2063         required_fragments: &["pub async fn wrap_message_file<T>(", "KIND_MESSAGE_FILE =>"],
   2064     },
   2065     EventBoundarySourceWitness {
   2066         relative_path: "crates/nostr/src/lib.rs",
   2067         required_fragments: &["pub mod nip17;"],
   2068     },
   2069 ];
   2070 
   2071 const GIFT_WRAP_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2072     EventBoundarySourceWitness {
   2073         relative_path: "crates/event/src/gift_wrap.rs",
   2074         required_fragments: &["pub struct GiftWrap"],
   2075     },
   2076     EventBoundarySourceWitness {
   2077         relative_path: "crates/event/src/kinds.rs",
   2078         required_fragments: &["pub const KIND_GIFT_WRAP: u32 = 1059;"],
   2079     },
   2080     EventBoundarySourceWitness {
   2081         relative_path: "crates/nostr/src/nip17.rs",
   2082         required_fragments: &["pub async fn unwrap_gift_wrap<T>("],
   2083     },
   2084     EventBoundarySourceWitness {
   2085         relative_path: "crates/nostr/src/lib.rs",
   2086         required_fragments: &["pub mod nip17;"],
   2087     },
   2088 ];
   2089 
   2090 const PUBLIC_FILE_METADATA_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2091     EventBoundarySourceWitness {
   2092         relative_path: "crates/event/src/file_metadata.rs",
   2093         required_fragments: &["pub struct FileMetadata"],
   2094     },
   2095     EventBoundarySourceWitness {
   2096         relative_path: "crates/event/src/kinds.rs",
   2097         required_fragments: &["pub const KIND_PUBLIC_FILE_METADATA: u32 = KIND_FILE_METADATA;"],
   2098     },
   2099 ];
   2100 
   2101 const REPORT_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2102     EventBoundarySourceWitness {
   2103         relative_path: "crates/event/src/report.rs",
   2104         required_fragments: &["pub struct Report"],
   2105     },
   2106     EventBoundarySourceWitness {
   2107         relative_path: "crates/event/src/kinds.rs",
   2108         required_fragments: &["pub const KIND_REPORT: u32 = 1984;"],
   2109     },
   2110 ];
   2111 
   2112 const LIST_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2113     EventBoundarySourceWitness {
   2114         relative_path: "crates/event/src/list.rs",
   2115         required_fragments: &["pub struct List"],
   2116     },
   2117     EventBoundarySourceWitness {
   2118         relative_path: "crates/event/src/kinds.rs",
   2119         required_fragments: &[
   2120             "pub const KIND_LIST_MUTE: u32 = 10000;",
   2121             "pub const KIND_LIST_GOOD_WIKI_RELAYS: u32 = 10102;",
   2122         ],
   2123     },
   2124 ];
   2125 
   2126 const RELAY_LIST_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2127     EventBoundarySourceWitness {
   2128         relative_path: "crates/event/src/list.rs",
   2129         required_fragments: &["pub struct List"],
   2130     },
   2131     EventBoundarySourceWitness {
   2132         relative_path: "crates/event/src/kinds.rs",
   2133         required_fragments: &["pub const KIND_LIST_READ_WRITE_RELAYS: u32 = 10002;"],
   2134     },
   2135 ];
   2136 
   2137 const LIST_SET_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2138     EventBoundarySourceWitness {
   2139         relative_path: "crates/event/src/list_set.rs",
   2140         required_fragments: &["pub struct ListSet"],
   2141     },
   2142     EventBoundarySourceWitness {
   2143         relative_path: "crates/event/src/kinds.rs",
   2144         required_fragments: &[
   2145             "pub const KIND_LIST_SET_FOLLOW: u32 = 30000;",
   2146             "pub const KIND_LIST_SET_MEDIA_STARTER_PACK: u32 = 39092;",
   2147         ],
   2148     },
   2149 ];
   2150 
   2151 const ARTICLE_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2152     EventBoundarySourceWitness {
   2153         relative_path: "crates/event/src/article.rs",
   2154         required_fragments: &["pub struct Article"],
   2155     },
   2156     EventBoundarySourceWitness {
   2157         relative_path: "crates/event/src/kinds.rs",
   2158         required_fragments: &["pub const KIND_ARTICLE: u32 = 30023;"],
   2159     },
   2160 ];
   2161 
   2162 const KNOWLEDGE_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2163     EventBoundarySourceWitness {
   2164         relative_path: "crates/event/src/knowledge.rs",
   2165         required_fragments: &[
   2166             "pub struct WikiArticle",
   2167             "pub struct KnowledgeClaim",
   2168             "pub struct KnowledgeFieldReport",
   2169             "pub struct EvidenceBounty",
   2170         ],
   2171     },
   2172     EventBoundarySourceWitness {
   2173         relative_path: "crates/event/src/kinds.rs",
   2174         required_fragments: &[
   2175             "pub const KIND_WIKI_MERGE_REQUEST: u32 = 818;",
   2176             "pub const KIND_KNOWLEDGE_CLAIM: u32 = 3460;",
   2177             "pub const KIND_KNOWLEDGE_SOURCE: u32 = 30450;",
   2178             "pub const KIND_WIKI_ARTICLE: u32 = 30818;",
   2179         ],
   2180     },
   2181     EventBoundarySourceWitness {
   2182         relative_path: "crates/event/src/contract/registry_v7.rs",
   2183         required_fragments: &[
   2184             "Reducer::KnowledgeProjection",
   2185             "\"radroots.wiki.article.v1\"",
   2186             "\"radroots.knowledge.claim.v1\"",
   2187             "pub fn validate_event_contract_shape",
   2188         ],
   2189     },
   2190 ];
   2191 
   2192 const APP_DATA_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2193     EventBoundarySourceWitness {
   2194         relative_path: "crates/event/src/app_data.rs",
   2195         required_fragments: &["pub struct AppData"],
   2196     },
   2197     EventBoundarySourceWitness {
   2198         relative_path: "crates/event/src/kinds.rs",
   2199         required_fragments: &["pub const KIND_APP_DATA: u32 = 30078;"],
   2200     },
   2201 ];
   2202 
   2203 const APP_HANDLER_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2204     EventBoundarySourceWitness {
   2205         relative_path: "crates/event/src/kinds.rs",
   2206         required_fragments: &["pub const KIND_APPLICATION_HANDLER: u32 = 31990;"],
   2207     },
   2208     EventBoundarySourceWitness {
   2209         relative_path: "crates/nostr/src/events/application_handler.rs",
   2210         required_fragments: &["pub fn build_application_handler_event("],
   2211     },
   2212 ];
   2213 
   2214 const CALENDAR_DATE_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2215     EventBoundarySourceWitness {
   2216         relative_path: "crates/event/src/calendar.rs",
   2217         required_fragments: &[
   2218             "pub struct AuthoredCalendarDateEvent",
   2219             "pub struct ParsedNip52CalendarDateEvent",
   2220             "pub struct AdmittedCalendarDateEvent",
   2221         ],
   2222     },
   2223     EventBoundarySourceWitness {
   2224         relative_path: "crates/event_codec/src/calendar/encode.rs",
   2225         required_fragments: &["pub fn date_to_wire_parts("],
   2226     },
   2227     EventBoundarySourceWitness {
   2228         relative_path: "crates/event_codec/src/calendar/decode.rs",
   2229         required_fragments: &[
   2230             "pub fn parse_nip52_calendar_date_event(",
   2231             "pub fn admit_radroots_calendar_date_event(",
   2232         ],
   2233     },
   2234     EventBoundarySourceWitness {
   2235         relative_path: "crates/event/src/kinds.rs",
   2236         required_fragments: &["pub const KIND_CALENDAR_DATE_EVENT: u32 = 31922;"],
   2237     },
   2238 ];
   2239 
   2240 const CALENDAR_TIME_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2241     EventBoundarySourceWitness {
   2242         relative_path: "crates/event/src/calendar.rs",
   2243         required_fragments: &[
   2244             "pub struct AuthoredCalendarTimeEvent",
   2245             "pub struct ParsedNip52CalendarTimeEvent",
   2246             "pub struct AdmittedCalendarTimeEvent",
   2247         ],
   2248     },
   2249     EventBoundarySourceWitness {
   2250         relative_path: "crates/event_codec/src/calendar/encode.rs",
   2251         required_fragments: &["pub fn time_to_wire_parts("],
   2252     },
   2253     EventBoundarySourceWitness {
   2254         relative_path: "crates/event_codec/src/calendar/decode.rs",
   2255         required_fragments: &[
   2256             "pub fn parse_nip52_calendar_time_event(",
   2257             "pub fn admit_radroots_calendar_time_event(",
   2258         ],
   2259     },
   2260     EventBoundarySourceWitness {
   2261         relative_path: "crates/event/src/kinds.rs",
   2262         required_fragments: &["pub const KIND_CALENDAR_TIME_EVENT: u32 = 31923;"],
   2263     },
   2264 ];
   2265 
   2266 const CALENDAR_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2267     EventBoundarySourceWitness {
   2268         relative_path: "crates/event/src/calendar.rs",
   2269         required_fragments: &[
   2270             "pub struct AuthoredCalendar {",
   2271             "pub struct ParsedNip52Calendar {",
   2272             "pub struct AdmittedCalendar {",
   2273         ],
   2274     },
   2275     EventBoundarySourceWitness {
   2276         relative_path: "crates/event_codec/src/calendar/encode.rs",
   2277         required_fragments: &["pub fn calendar_to_wire_parts("],
   2278     },
   2279     EventBoundarySourceWitness {
   2280         relative_path: "crates/event_codec/src/calendar/decode.rs",
   2281         required_fragments: &[
   2282             "pub fn parse_nip52_calendar(",
   2283             "pub fn admit_radroots_calendar(",
   2284         ],
   2285     },
   2286     EventBoundarySourceWitness {
   2287         relative_path: "crates/event/src/kinds.rs",
   2288         required_fragments: &["pub const KIND_CALENDAR: u32 = KIND_LIST_SET_CALENDAR;"],
   2289     },
   2290 ];
   2291 
   2292 const CALENDAR_RSVP_WITNESSES: [EventBoundarySourceWitness; 4] = [
   2293     EventBoundarySourceWitness {
   2294         relative_path: "crates/event/src/calendar.rs",
   2295         required_fragments: &[
   2296             "pub struct AuthoredCalendarEventRsvp {",
   2297             "pub struct ParsedNip52CalendarEventRsvp {",
   2298             "pub struct AdmittedCalendarEventRsvp {",
   2299         ],
   2300     },
   2301     EventBoundarySourceWitness {
   2302         relative_path: "crates/event_codec/src/calendar/encode.rs",
   2303         required_fragments: &["pub fn rsvp_to_wire_parts("],
   2304     },
   2305     EventBoundarySourceWitness {
   2306         relative_path: "crates/event_codec/src/calendar/decode.rs",
   2307         required_fragments: &[
   2308             "pub fn parse_nip52_calendar_event_rsvp(",
   2309             "pub fn admit_radroots_calendar_event_rsvp(",
   2310         ],
   2311     },
   2312     EventBoundarySourceWitness {
   2313         relative_path: "crates/event/src/kinds.rs",
   2314         required_fragments: &["pub const KIND_CALENDAR_EVENT_RSVP: u32 = 31925;"],
   2315     },
   2316 ];
   2317 
   2318 const FARM_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2319     EventBoundarySourceWitness {
   2320         relative_path: "crates/event/src/farm.rs",
   2321         required_fragments: &["pub struct Farm"],
   2322     },
   2323     EventBoundarySourceWitness {
   2324         relative_path: "crates/event/src/kinds.rs",
   2325         required_fragments: &["pub const KIND_FARM: u32 = 30340;"],
   2326     },
   2327 ];
   2328 
   2329 const PLOT_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2330     EventBoundarySourceWitness {
   2331         relative_path: "crates/event/src/plot.rs",
   2332         required_fragments: &["pub struct Plot"],
   2333     },
   2334     EventBoundarySourceWitness {
   2335         relative_path: "crates/event/src/kinds.rs",
   2336         required_fragments: &["pub const KIND_PLOT: u32 = 30350;"],
   2337     },
   2338 ];
   2339 
   2340 const COOP_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2341     EventBoundarySourceWitness {
   2342         relative_path: "crates/event/src/coop.rs",
   2343         required_fragments: &["pub struct Coop"],
   2344     },
   2345     EventBoundarySourceWitness {
   2346         relative_path: "crates/event/src/kinds.rs",
   2347         required_fragments: &["pub const KIND_COOP: u32 = 30360;"],
   2348     },
   2349 ];
   2350 
   2351 const DOCUMENT_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2352     EventBoundarySourceWitness {
   2353         relative_path: "crates/event/src/document.rs",
   2354         required_fragments: &["pub struct Document"],
   2355     },
   2356     EventBoundarySourceWitness {
   2357         relative_path: "crates/event/src/kinds.rs",
   2358         required_fragments: &["pub const KIND_DOCUMENT: u32 = 30361;"],
   2359     },
   2360 ];
   2361 
   2362 const RESOURCE_AREA_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2363     EventBoundarySourceWitness {
   2364         relative_path: "crates/event/src/resource_area.rs",
   2365         required_fragments: &["pub struct ResourceArea"],
   2366     },
   2367     EventBoundarySourceWitness {
   2368         relative_path: "crates/event/src/kinds.rs",
   2369         required_fragments: &["pub const KIND_RESOURCE_AREA: u32 = 30370;"],
   2370     },
   2371 ];
   2372 
   2373 const RESOURCE_CAP_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2374     EventBoundarySourceWitness {
   2375         relative_path: "crates/event/src/resource_cap.rs",
   2376         required_fragments: &["pub struct ResourceHarvestCap"],
   2377     },
   2378     EventBoundarySourceWitness {
   2379         relative_path: "crates/event/src/kinds.rs",
   2380         required_fragments: &["pub const KIND_RESOURCE_HARVEST_CAP: u32 = 30371;"],
   2381     },
   2382 ];
   2383 
   2384 const OPERATIONAL_LISTING_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2385     EventBoundarySourceWitness {
   2386         relative_path: "crates/event/src/operational_listing.rs",
   2387         required_fragments: &["pub struct OperationalListing"],
   2388     },
   2389     EventBoundarySourceWitness {
   2390         relative_path: "crates/event/src/kinds.rs",
   2391         required_fragments: &["pub const KIND_CLASSIFIED_LISTING: u32 = 30402;"],
   2392     },
   2393 ];
   2394 
   2395 const FOOD_AVAILABILITY_WITNESSES: [EventBoundarySourceWitness; 6] = [
   2396     EventBoundarySourceWitness {
   2397         relative_path: "crates/event/src/food_availability.rs",
   2398         required_fragments: &[
   2399             "pub const RADROOTS_FOOD_AVAILABILITY_CONTRACT_ID: &str",
   2400             "pub struct FoodAvailabilityDetails",
   2401         ],
   2402     },
   2403     EventBoundarySourceWitness {
   2404         relative_path: "crates/event/src/kinds.rs",
   2405         required_fragments: &["pub const KIND_CLASSIFIED_LISTING: u32 = 30402;"],
   2406     },
   2407     EventBoundarySourceWitness {
   2408         relative_path: "crates/event_codec/src/food_availability/authored.rs",
   2409         required_fragments: &["pub fn authored_food_availability_to_wire_parts("],
   2410     },
   2411     EventBoundarySourceWitness {
   2412         relative_path: "crates/event_codec/src/food_availability/inbound/registry_v7.rs",
   2413         required_fragments: &[
   2414             "pub struct RadrootsInboundFoodAvailabilityProjection",
   2415             "pub fn project_verified_food_availability_event(",
   2416         ],
   2417     },
   2418     EventBoundarySourceWitness {
   2419         relative_path: "crates/event_codec/src/food_availability/admission.rs",
   2420         required_fragments: &[
   2421             "pub struct RadrootsAdmittedFoodAvailabilityEvent",
   2422             "pub fn verify_and_admit_food_availability_event(",
   2423         ],
   2424     },
   2425     EventBoundarySourceWitness {
   2426         relative_path: "crates/event_codec/src/food_availability/revision.rs",
   2427         required_fragments: &["pub fn validate_food_availability_revision("],
   2428     },
   2429 ];
   2430 
   2431 const DVM_REQUEST_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2432     EventBoundarySourceWitness {
   2433         relative_path: "crates/event/src/job_request.rs",
   2434         required_fragments: &["pub struct JobRequest"],
   2435     },
   2436     EventBoundarySourceWitness {
   2437         relative_path: "crates/event/src/kinds.rs",
   2438         required_fragments: &[
   2439             "pub const KIND_JOB_REQUEST_MIN: u32 = 5000;",
   2440             "pub const KIND_JOB_REQUEST_MAX: u32 = 5999;",
   2441         ],
   2442     },
   2443 ];
   2444 
   2445 const DVM_RESULT_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2446     EventBoundarySourceWitness {
   2447         relative_path: "crates/event/src/job_result.rs",
   2448         required_fragments: &["pub struct JobResult"],
   2449     },
   2450     EventBoundarySourceWitness {
   2451         relative_path: "crates/event/src/kinds.rs",
   2452         required_fragments: &[
   2453             "pub const KIND_JOB_RESULT_MIN: u32 = 6000;",
   2454             "pub const KIND_JOB_RESULT_MAX: u32 = 6999;",
   2455         ],
   2456     },
   2457 ];
   2458 
   2459 const DVM_FEEDBACK_WITNESSES: [EventBoundarySourceWitness; 2] = [
   2460     EventBoundarySourceWitness {
   2461         relative_path: "crates/event/src/job_feedback.rs",
   2462         required_fragments: &["pub struct JobFeedback"],
   2463     },
   2464     EventBoundarySourceWitness {
   2465         relative_path: "crates/event/src/kinds.rs",
   2466         required_fragments: &["pub const KIND_JOB_FEEDBACK: u32 = 7000;"],
   2467     },
   2468 ];
   2469 
   2470 const TRADE_PROPOSAL_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2471     EventBoundarySourceWitness {
   2472         relative_path: "crates/event/src/kinds.rs",
   2473         required_fragments: &["pub const KIND_TRADE_PROPOSAL: u32 = 3470;"],
   2474     },
   2475     EventBoundarySourceWitness {
   2476         relative_path: "crates/event/src/trade.rs",
   2477         required_fragments: &[
   2478             "pub const RADROOTS_TRADE_PROPOSAL_CONTRACT_ID: &str",
   2479             "Self::Proposal => KIND_TRADE_PROPOSAL",
   2480         ],
   2481     },
   2482     EventBoundarySourceWitness {
   2483         relative_path: "crates/event_codec/src/trade/mod.rs",
   2484         required_fragments: &[
   2485             "pub fn trade_mutation_event_build",
   2486             "pub fn trade_mutation_from_event",
   2487             "pub fn trade_mutation_from_verified_event",
   2488             "pub fn validate_trade_mutation_tags",
   2489         ],
   2490     },
   2491 ];
   2492 
   2493 const TRADE_DECISION_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2494     EventBoundarySourceWitness {
   2495         relative_path: "crates/event/src/kinds.rs",
   2496         required_fragments: &["pub const KIND_TRADE_DECISION: u32 = 3471;"],
   2497     },
   2498     EventBoundarySourceWitness {
   2499         relative_path: "crates/event/src/trade.rs",
   2500         required_fragments: &[
   2501             "pub const RADROOTS_TRADE_DECISION_CONTRACT_ID: &str",
   2502             "Self::Decision => KIND_TRADE_DECISION",
   2503         ],
   2504     },
   2505     EventBoundarySourceWitness {
   2506         relative_path: "crates/event_codec/src/trade/mod.rs",
   2507         required_fragments: &[
   2508             "pub fn trade_mutation_event_build",
   2509             "pub fn trade_mutation_from_event",
   2510             "pub fn trade_mutation_from_verified_event",
   2511             "pub fn validate_trade_mutation_tags",
   2512         ],
   2513     },
   2514 ];
   2515 
   2516 const TRADE_REVISION_PROPOSAL_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2517     EventBoundarySourceWitness {
   2518         relative_path: "crates/event/src/kinds.rs",
   2519         required_fragments: &["pub const KIND_TRADE_REVISION_PROPOSAL: u32 = 3472;"],
   2520     },
   2521     EventBoundarySourceWitness {
   2522         relative_path: "crates/event/src/trade.rs",
   2523         required_fragments: &[
   2524             "pub const RADROOTS_TRADE_REVISION_PROPOSAL_CONTRACT_ID: &str",
   2525             "Self::RevisionProposal => KIND_TRADE_REVISION_PROPOSAL",
   2526         ],
   2527     },
   2528     EventBoundarySourceWitness {
   2529         relative_path: "crates/event_codec/src/trade/mod.rs",
   2530         required_fragments: &[
   2531             "pub fn trade_mutation_event_build",
   2532             "pub fn trade_mutation_from_event",
   2533             "pub fn trade_mutation_from_verified_event",
   2534             "pub fn validate_trade_mutation_tags",
   2535         ],
   2536     },
   2537 ];
   2538 
   2539 const TRADE_REVISION_DECISION_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2540     EventBoundarySourceWitness {
   2541         relative_path: "crates/event/src/kinds.rs",
   2542         required_fragments: &["pub const KIND_TRADE_REVISION_DECISION: u32 = 3473;"],
   2543     },
   2544     EventBoundarySourceWitness {
   2545         relative_path: "crates/event/src/trade.rs",
   2546         required_fragments: &[
   2547             "pub const RADROOTS_TRADE_REVISION_DECISION_CONTRACT_ID: &str",
   2548             "Self::RevisionDecision => KIND_TRADE_REVISION_DECISION",
   2549         ],
   2550     },
   2551     EventBoundarySourceWitness {
   2552         relative_path: "crates/event_codec/src/trade/mod.rs",
   2553         required_fragments: &[
   2554             "pub fn trade_mutation_event_build",
   2555             "pub fn trade_mutation_from_event",
   2556             "pub fn trade_mutation_from_verified_event",
   2557             "pub fn validate_trade_mutation_tags",
   2558         ],
   2559     },
   2560 ];
   2561 
   2562 const TRADE_CANCELLATION_WITNESSES: [EventBoundarySourceWitness; 3] = [
   2563     EventBoundarySourceWitness {
   2564         relative_path: "crates/event/src/kinds.rs",
   2565         required_fragments: &["pub const KIND_TRADE_CANCELLATION: u32 = 3474;"],
   2566     },
   2567     EventBoundarySourceWitness {
   2568         relative_path: "crates/event/src/trade.rs",
   2569         required_fragments: &[
   2570             "pub const RADROOTS_TRADE_CANCELLATION_CONTRACT_ID: &str",
   2571             "Self::Cancellation => KIND_TRADE_CANCELLATION",
   2572         ],
   2573     },
   2574     EventBoundarySourceWitness {
   2575         relative_path: "crates/event_codec/src/trade/mod.rs",
   2576         required_fragments: &[
   2577             "pub fn trade_mutation_event_build",
   2578             "pub fn trade_mutation_from_event",
   2579             "pub fn trade_mutation_from_verified_event",
   2580             "pub fn validate_trade_mutation_tags",
   2581         ],
   2582     },
   2583 ];
   2584 
   2585 const RELAY_DOC_WITNESSES: [EventBoundarySourceWitness; 1] = [EventBoundarySourceWitness {
   2586     relative_path: "crates/event/src/relay_document.rs",
   2587     required_fragments: &["pub struct RelayDocument"],
   2588 }];
   2589 
   2590 const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 43] = [
   2591     EventBoundaryExpectation {
   2592         domain: "profile",
   2593         kind: "0",
   2594         radroots_type: "AuthoredProfile / RadrootsInboundProfileMetadata",
   2595         rpc_methods: &[
   2596             "events.profile.publish",
   2597             "events.profile.list",
   2598             "events.profile.get",
   2599         ],
   2600         witnesses: &PROFILE_WITNESSES,
   2601     },
   2602     EventBoundaryExpectation {
   2603         domain: "follow",
   2604         kind: "3",
   2605         radroots_type: "Follow",
   2606         rpc_methods: &[
   2607             "events.follow.publish",
   2608             "events.follow.list",
   2609             "events.follow.get",
   2610         ],
   2611         witnesses: &FOLLOW_WITNESSES,
   2612     },
   2613     EventBoundaryExpectation {
   2614         domain: "post",
   2615         kind: "1",
   2616         radroots_type: "AuthoredUpdate / AuthoredPhotoUpdate / AuthoredAsk / RadrootsInboundPostProjection",
   2617         rpc_methods: &["events.post.publish", "events.post.list", "events.post.get"],
   2618         witnesses: &POST_WITNESSES,
   2619     },
   2620     EventBoundaryExpectation {
   2621         domain: "reply",
   2622         kind: "1",
   2623         radroots_type: "AuthoredNip10Reply / RadrootsInboundNip10ReplyProjection / RadrootsAdmittedNip10ReplyEvent / Nip10ReplyBuilder",
   2624         rpc_methods: &[
   2625             "social.reply.build_authored_draft",
   2626             "social.reply.project_verified_event",
   2627             "social.reply.verify_and_admit_event",
   2628         ],
   2629         witnesses: &REPLY_WITNESSES,
   2630     },
   2631     EventBoundaryExpectation {
   2632         domain: "comment",
   2633         kind: "1111",
   2634         radroots_type: "AuthoredNip22Comment / RadrootsInboundNip22CommentProjection / RadrootsAdmittedNip22CommentEvent / Nip22CommentBuilder",
   2635         rpc_methods: &[
   2636             "social.comment.build_authored_draft",
   2637             "social.comment.project_verified_event",
   2638             "social.comment.verify_and_admit_event",
   2639         ],
   2640         witnesses: &COMMENT_WITNESSES,
   2641     },
   2642     EventBoundaryExpectation {
   2643         domain: "deletion_request",
   2644         kind: "5",
   2645         radroots_type: "AuthoredNip09DeletionRequest / RadrootsInboundNip09DeletionProjection / RadrootsAdmittedNip09DeletionRequestEvent / RadrootsNip09SuppressionDecision / Nip09DeletionRequestBuilder",
   2646         rpc_methods: &[
   2647             "social.deletion_request.build_authored_draft",
   2648             "social.deletion_request.project_verified_event",
   2649             "social.deletion_request.verify_and_admit_event",
   2650             "social.deletion_request.evaluate_suppression",
   2651         ],
   2652         witnesses: &DELETION_WITNESSES,
   2653     },
   2654     EventBoundaryExpectation {
   2655         domain: "reaction",
   2656         kind: "7",
   2657         radroots_type: "Reaction",
   2658         rpc_methods: &[
   2659             "events.reaction.publish",
   2660             "events.reaction.list",
   2661             "events.reaction.get",
   2662         ],
   2663         witnesses: &REACTION_WITNESSES,
   2664     },
   2665     EventBoundaryExpectation {
   2666         domain: "repost",
   2667         kind: "6",
   2668         radroots_type: "Repost",
   2669         rpc_methods: &[
   2670             "events.repost.publish",
   2671             "events.repost.list",
   2672             "events.repost.get",
   2673         ],
   2674         witnesses: &REPOST_WITNESSES,
   2675     },
   2676     EventBoundaryExpectation {
   2677         domain: "generic_repost",
   2678         kind: "16",
   2679         radroots_type: "GenericRepost",
   2680         rpc_methods: &[
   2681             "events.generic_repost.publish",
   2682             "events.generic_repost.list",
   2683             "events.generic_repost.get",
   2684         ],
   2685         witnesses: &GENERIC_REPOST_WITNESSES,
   2686     },
   2687     EventBoundaryExpectation {
   2688         domain: "seal",
   2689         kind: "13",
   2690         radroots_type: "Seal",
   2691         rpc_methods: &["events.seal.encode", "events.seal.decode"],
   2692         witnesses: &SEAL_WITNESSES,
   2693     },
   2694     EventBoundaryExpectation {
   2695         domain: "message",
   2696         kind: "14",
   2697         radroots_type: "Message",
   2698         rpc_methods: &[
   2699             "events.message.publish",
   2700             "events.message.list",
   2701             "events.message.get",
   2702         ],
   2703         witnesses: &MESSAGE_WITNESSES,
   2704     },
   2705     EventBoundaryExpectation {
   2706         domain: "message_file",
   2707         kind: "15",
   2708         radroots_type: "MessageFile",
   2709         rpc_methods: &[
   2710             "events.message_file.publish",
   2711             "events.message_file.list",
   2712             "events.message_file.get",
   2713         ],
   2714         witnesses: &MESSAGE_FILE_WITNESSES,
   2715     },
   2716     EventBoundaryExpectation {
   2717         domain: "gift_wrap",
   2718         kind: "1059",
   2719         radroots_type: "GiftWrap",
   2720         rpc_methods: &[
   2721             "events.gift_wrap.publish",
   2722             "events.gift_wrap.list",
   2723             "events.gift_wrap.get",
   2724         ],
   2725         witnesses: &GIFT_WRAP_WITNESSES,
   2726     },
   2727     EventBoundaryExpectation {
   2728         domain: "public_file_metadata",
   2729         kind: "1063",
   2730         radroots_type: "FileMetadata",
   2731         rpc_methods: &[
   2732             "events.public_file_metadata.publish",
   2733             "events.public_file_metadata.list",
   2734             "events.public_file_metadata.get",
   2735         ],
   2736         witnesses: &PUBLIC_FILE_METADATA_WITNESSES,
   2737     },
   2738     EventBoundaryExpectation {
   2739         domain: "report",
   2740         kind: "1984",
   2741         radroots_type: "Report",
   2742         rpc_methods: &[
   2743             "events.report.publish",
   2744             "events.report.list",
   2745             "events.report.get",
   2746         ],
   2747         witnesses: &REPORT_WITNESSES,
   2748     },
   2749     EventBoundaryExpectation {
   2750         domain: "list",
   2751         kind: "10000..10102",
   2752         radroots_type: "List",
   2753         rpc_methods: &["events.list.publish", "events.list.list", "events.list.get"],
   2754         witnesses: &LIST_WITNESSES,
   2755     },
   2756     EventBoundaryExpectation {
   2757         domain: "relay_list",
   2758         kind: "10002",
   2759         radroots_type: "List",
   2760         rpc_methods: &[
   2761             "events.relay_list.publish",
   2762             "events.relay_list.list",
   2763             "events.relay_list.get",
   2764         ],
   2765         witnesses: &RELAY_LIST_WITNESSES,
   2766     },
   2767     EventBoundaryExpectation {
   2768         domain: "list_set",
   2769         kind: "30000..30007, 30015, 30030, 30063, 30267, 39089, 39092",
   2770         radroots_type: "ListSet",
   2771         rpc_methods: &[
   2772             "events.list_set.publish",
   2773             "events.list_set.list",
   2774             "events.list_set.get",
   2775         ],
   2776         witnesses: &LIST_SET_WITNESSES,
   2777     },
   2778     EventBoundaryExpectation {
   2779         domain: "article",
   2780         kind: "30023",
   2781         radroots_type: "Article",
   2782         rpc_methods: &[
   2783             "events.article.publish",
   2784             "events.article.list",
   2785             "events.article.get",
   2786         ],
   2787         witnesses: &ARTICLE_WITNESSES,
   2788     },
   2789     EventBoundaryExpectation {
   2790         domain: "knowledge",
   2791         kind: "818, 3460..3465, 30450..30451, 30818..30819",
   2792         radroots_type: "RadrootsKnowledgeEvent",
   2793         rpc_methods: &[
   2794             "events.knowledge.publish",
   2795             "events.knowledge.list",
   2796             "events.knowledge.get",
   2797         ],
   2798         witnesses: &KNOWLEDGE_WITNESSES,
   2799     },
   2800     EventBoundaryExpectation {
   2801         domain: "app_data",
   2802         kind: "30078",
   2803         radroots_type: "AppData",
   2804         rpc_methods: &[
   2805             "events.app_data.publish",
   2806             "events.app_data.list",
   2807             "events.app_data.get",
   2808         ],
   2809         witnesses: &APP_DATA_WITNESSES,
   2810     },
   2811     EventBoundaryExpectation {
   2812         domain: "app_handler",
   2813         kind: "31990",
   2814         radroots_type: "KIND_APPLICATION_HANDLER",
   2815         rpc_methods: &[
   2816             "events.app_handler.publish",
   2817             "events.app_handler.list",
   2818             "events.app_handler.get",
   2819         ],
   2820         witnesses: &APP_HANDLER_WITNESSES,
   2821     },
   2822     EventBoundaryExpectation {
   2823         domain: "calendar_date",
   2824         kind: "31922",
   2825         radroots_type: "AuthoredCalendarDateEvent / ParsedNip52CalendarDateEvent / AdmittedCalendarDateEvent",
   2826         rpc_methods: &[
   2827             "events.calendar_date.publish",
   2828             "events.calendar_date.list",
   2829             "events.calendar_date.get",
   2830         ],
   2831         witnesses: &CALENDAR_DATE_WITNESSES,
   2832     },
   2833     EventBoundaryExpectation {
   2834         domain: "calendar_time",
   2835         kind: "31923",
   2836         radroots_type: "AuthoredCalendarTimeEvent / ParsedNip52CalendarTimeEvent / AdmittedCalendarTimeEvent",
   2837         rpc_methods: &[
   2838             "events.calendar_time.publish",
   2839             "events.calendar_time.list",
   2840             "events.calendar_time.get",
   2841         ],
   2842         witnesses: &CALENDAR_TIME_WITNESSES,
   2843     },
   2844     EventBoundaryExpectation {
   2845         domain: "calendar",
   2846         kind: "31924",
   2847         radroots_type: "AuthoredCalendar / ParsedNip52Calendar / AdmittedCalendar",
   2848         rpc_methods: &[
   2849             "events.calendar.publish",
   2850             "events.calendar.list",
   2851             "events.calendar.get",
   2852         ],
   2853         witnesses: &CALENDAR_WITNESSES,
   2854     },
   2855     EventBoundaryExpectation {
   2856         domain: "calendar_rsvp",
   2857         kind: "31925",
   2858         radroots_type: "AuthoredCalendarEventRsvp / ParsedNip52CalendarEventRsvp / AdmittedCalendarEventRsvp",
   2859         rpc_methods: &[
   2860             "events.calendar_rsvp.publish",
   2861             "events.calendar_rsvp.list",
   2862             "events.calendar_rsvp.get",
   2863         ],
   2864         witnesses: &CALENDAR_RSVP_WITNESSES,
   2865     },
   2866     EventBoundaryExpectation {
   2867         domain: "farm",
   2868         kind: "30340",
   2869         radroots_type: "Farm",
   2870         rpc_methods: &["events.farm.publish", "events.farm.list", "events.farm.get"],
   2871         witnesses: &FARM_WITNESSES,
   2872     },
   2873     EventBoundaryExpectation {
   2874         domain: "plot",
   2875         kind: "30350",
   2876         radroots_type: "Plot",
   2877         rpc_methods: &["events.plot.publish", "events.plot.list", "events.plot.get"],
   2878         witnesses: &PLOT_WITNESSES,
   2879     },
   2880     EventBoundaryExpectation {
   2881         domain: "coop",
   2882         kind: "30360",
   2883         radroots_type: "Coop",
   2884         rpc_methods: &["events.coop.publish", "events.coop.list", "events.coop.get"],
   2885         witnesses: &COOP_WITNESSES,
   2886     },
   2887     EventBoundaryExpectation {
   2888         domain: "document",
   2889         kind: "30361",
   2890         radroots_type: "Document",
   2891         rpc_methods: &[
   2892             "events.document.publish",
   2893             "events.document.list",
   2894             "events.document.get",
   2895         ],
   2896         witnesses: &DOCUMENT_WITNESSES,
   2897     },
   2898     EventBoundaryExpectation {
   2899         domain: "resource_area",
   2900         kind: "30370",
   2901         radroots_type: "ResourceArea",
   2902         rpc_methods: &[
   2903             "events.resource_area.publish",
   2904             "events.resource_area.list",
   2905             "events.resource_area.get",
   2906         ],
   2907         witnesses: &RESOURCE_AREA_WITNESSES,
   2908     },
   2909     EventBoundaryExpectation {
   2910         domain: "resource_cap",
   2911         kind: "30371",
   2912         radroots_type: "ResourceHarvestCap",
   2913         rpc_methods: &[
   2914             "events.resource_cap.publish",
   2915             "events.resource_cap.list",
   2916             "events.resource_cap.get",
   2917         ],
   2918         witnesses: &RESOURCE_CAP_WITNESSES,
   2919     },
   2920     EventBoundaryExpectation {
   2921         domain: "food_availability",
   2922         kind: "30402",
   2923         radroots_type: "FoodAvailabilityDetails / RadrootsInboundFoodAvailabilityProjection / RadrootsAdmittedFoodAvailabilityEvent / FoodAvailabilityBuilder",
   2924         rpc_methods: &[
   2925             "food_availability.build_authored_draft",
   2926             "food_availability.project_verified_event",
   2927             "food_availability.verify_and_admit_event",
   2928             "food_availability.validate_revision",
   2929         ],
   2930         witnesses: &FOOD_AVAILABILITY_WITNESSES,
   2931     },
   2932     EventBoundaryExpectation {
   2933         domain: "operational_listing",
   2934         kind: "30402",
   2935         radroots_type: "OperationalListing",
   2936         rpc_methods: &[
   2937             "events.operational_listing.publish",
   2938             "events.operational_listing.list",
   2939             "events.operational_listing.get",
   2940         ],
   2941         witnesses: &OPERATIONAL_LISTING_WITNESSES,
   2942     },
   2943     EventBoundaryExpectation {
   2944         domain: "dvm_request",
   2945         kind: "5000-5999",
   2946         radroots_type: "JobRequest",
   2947         rpc_methods: &[
   2948             "events.dvm_request.publish",
   2949             "events.dvm_request.list",
   2950             "events.dvm_request.get",
   2951         ],
   2952         witnesses: &DVM_REQUEST_WITNESSES,
   2953     },
   2954     EventBoundaryExpectation {
   2955         domain: "dvm_result",
   2956         kind: "6000-6999",
   2957         radroots_type: "JobResult",
   2958         rpc_methods: &[
   2959             "events.dvm_result.publish",
   2960             "events.dvm_result.list",
   2961             "events.dvm_result.get",
   2962         ],
   2963         witnesses: &DVM_RESULT_WITNESSES,
   2964     },
   2965     EventBoundaryExpectation {
   2966         domain: "dvm_feedback",
   2967         kind: "7000",
   2968         radroots_type: "JobFeedback",
   2969         rpc_methods: &[
   2970             "events.dvm_feedback.publish",
   2971             "events.dvm_feedback.list",
   2972             "events.dvm_feedback.get",
   2973         ],
   2974         witnesses: &DVM_FEEDBACK_WITNESSES,
   2975     },
   2976     EventBoundaryExpectation {
   2977         domain: "trade:proposal",
   2978         kind: "3470",
   2979         radroots_type: "TradeMutationEnvelopeV1",
   2980         rpc_methods: &[
   2981             "trade.get_trade",
   2982             "trade.list_trades",
   2983             "trade.submit_proposal",
   2984         ],
   2985         witnesses: &TRADE_PROPOSAL_WITNESSES,
   2986     },
   2987     EventBoundaryExpectation {
   2988         domain: "trade:decision",
   2989         kind: "3471",
   2990         radroots_type: "TradeMutationEnvelopeV1",
   2991         rpc_methods: &[
   2992             "trade.decide_candidate",
   2993             "trade.get_trade",
   2994             "trade.list_trades",
   2995         ],
   2996         witnesses: &TRADE_DECISION_WITNESSES,
   2997     },
   2998     EventBoundaryExpectation {
   2999         domain: "trade:revision_proposal",
   3000         kind: "3472",
   3001         radroots_type: "TradeMutationEnvelopeV1",
   3002         rpc_methods: &[
   3003             "trade.get_trade",
   3004             "trade.list_trades",
   3005             "trade.propose_revision",
   3006         ],
   3007         witnesses: &TRADE_REVISION_PROPOSAL_WITNESSES,
   3008     },
   3009     EventBoundaryExpectation {
   3010         domain: "trade:revision_decision",
   3011         kind: "3473",
   3012         radroots_type: "TradeMutationEnvelopeV1",
   3013         rpc_methods: &[
   3014             "trade.decide_candidate",
   3015             "trade.get_trade",
   3016             "trade.list_trades",
   3017         ],
   3018         witnesses: &TRADE_REVISION_DECISION_WITNESSES,
   3019     },
   3020     EventBoundaryExpectation {
   3021         domain: "trade:cancellation",
   3022         kind: "3474",
   3023         radroots_type: "TradeMutationEnvelopeV1",
   3024         rpc_methods: &["trade.cancel_trade", "trade.get_trade", "trade.list_trades"],
   3025         witnesses: &TRADE_CANCELLATION_WITNESSES,
   3026     },
   3027     EventBoundaryExpectation {
   3028         domain: "relay_doc",
   3029         kind: "N/A",
   3030         radroots_type: "RelayDocument",
   3031         rpc_methods: &["system.relay_doc.get"],
   3032         witnesses: &RELAY_DOC_WITNESSES,
   3033     },
   3034 ];
   3035 
   3036 #[derive(Debug, Deserialize)]
   3037 struct ReleaseContractFile {
   3038     release: ReleaseSection,
   3039     #[serde(default)]
   3040     publication: Option<PublicationControl>,
   3041     #[serde(default)]
   3042     workspace_classification: Option<WorkspaceReleaseClassification>,
   3043     #[serde(default)]
   3044     classification: ReleaseClassification,
   3045     #[serde(default)]
   3046     publish: Option<ReleaseCrateSet>,
   3047     #[serde(default)]
   3048     internal: Option<ReleaseCrateSet>,
   3049     publish_order: ReleaseCrateSet,
   3050 }
   3051 
   3052 #[derive(Debug, Default, Deserialize)]
   3053 struct ReleaseClassification {
   3054     #[serde(default)]
   3055     public: Vec<String>,
   3056     #[serde(default)]
   3057     internal: Vec<String>,
   3058     #[serde(default)]
   3059     deferred: Vec<String>,
   3060     #[serde(default)]
   3061     retired: Vec<String>,
   3062     #[serde(default)]
   3063     yank_only: Vec<String>,
   3064 }
   3065 
   3066 #[derive(Debug, Deserialize)]
   3067 struct ReleaseSection {
   3068     version: String,
   3069 }
   3070 
   3071 #[derive(Debug, Deserialize)]
   3072 struct PublicationControl {
   3073     frozen: bool,
   3074     registry: String,
   3075     final_enablement_step: u16,
   3076     #[serde(default)]
   3077     spec_id: String,
   3078     #[serde(default)]
   3079     approved_packages: Vec<String>,
   3080     #[serde(default)]
   3081     local_packages: Vec<String>,
   3082     #[serde(default)]
   3083     external_packages: Vec<String>,
   3084 }
   3085 
   3086 #[derive(Debug, Deserialize)]
   3087 struct WorkspaceReleaseClassification {
   3088     #[serde(default)]
   3089     private: Vec<String>,
   3090     #[serde(default)]
   3091     build_codegen: Vec<String>,
   3092     #[serde(default)]
   3093     test_support: Vec<String>,
   3094     #[serde(default)]
   3095     preview: Vec<String>,
   3096     #[serde(default)]
   3097     retired: Vec<String>,
   3098 }
   3099 
   3100 #[derive(Debug, Deserialize)]
   3101 struct CratesReleaseArchitecture {
   3102     spec_id: String,
   3103     package_count: usize,
   3104     repositories: CratesReleaseRepositories,
   3105     package: Vec<CratesReleasePackage>,
   3106 }
   3107 
   3108 #[derive(Debug, Deserialize)]
   3109 struct CratesReleaseRepositories {
   3110     lib: CratesReleaseRepository,
   3111     sdk: CratesReleaseRepository,
   3112 }
   3113 
   3114 #[derive(Debug, Deserialize)]
   3115 struct CratesReleaseRepository {
   3116     version: String,
   3117     packages: Vec<String>,
   3118 }
   3119 
   3120 #[derive(Debug, Deserialize)]
   3121 struct CratesReleasePackage {
   3122     name: String,
   3123 }
   3124 
   3125 #[derive(Debug, Deserialize)]
   3126 struct ConsolidationReleaseOwnership {
   3127     canonical_rust_repository: String,
   3128 }
   3129 
   3130 #[derive(Debug, Deserialize)]
   3131 struct ReleaseCrateSet {
   3132     crates: Vec<String>,
   3133 }
   3134 
   3135 #[derive(Debug, Deserialize)]
   3136 #[serde(deny_unknown_fields)]
   3137 struct ConformanceVectorFile {
   3138     suite: String,
   3139     contract_version: String,
   3140     vectors: Vec<ConformanceVectorEntry>,
   3141 }
   3142 
   3143 #[allow(dead_code)]
   3144 #[derive(Debug, Deserialize)]
   3145 #[serde(deny_unknown_fields)]
   3146 struct ConformanceVectorEntry {
   3147     id: String,
   3148     kind: String,
   3149     input: Value,
   3150     expected: Option<Value>,
   3151     expected_error_contains: Option<String>,
   3152 }
   3153 
   3154 impl ConformanceVectorEntry {
   3155     fn expected_value(&self) -> Result<&Value, String> {
   3156         self.expected.as_ref().ok_or_else(|| {
   3157             format!(
   3158                 "conformance vector {} does not define an expected output",
   3159                 self.id
   3160             )
   3161         })
   3162     }
   3163 }
   3164 
   3165 impl ReleaseContractFile {
   3166     fn uses_classification(&self) -> bool {
   3167         !self.classification.public.is_empty()
   3168             || !self.classification.internal.is_empty()
   3169             || !self.classification.deferred.is_empty()
   3170             || !self.classification.retired.is_empty()
   3171             || !self.classification.yank_only.is_empty()
   3172     }
   3173 
   3174     fn public_crates(&self) -> Vec<String> {
   3175         if let Some(publication) = &self.publication
   3176             && !publication.local_packages.is_empty()
   3177         {
   3178             return publication.local_packages.clone();
   3179         }
   3180         if self.uses_classification() {
   3181             return self.classification.public.clone();
   3182         }
   3183         self.publish
   3184             .as_ref()
   3185             .map(|set| set.crates.clone())
   3186             .unwrap_or_default()
   3187     }
   3188 
   3189     fn internal_crates(&self) -> Vec<String> {
   3190         if self.uses_classification() {
   3191             return self.classification.internal.clone();
   3192         }
   3193         self.internal
   3194             .as_ref()
   3195             .map(|set| set.crates.clone())
   3196             .unwrap_or_default()
   3197     }
   3198 
   3199     fn deferred_crates(&self) -> Vec<String> {
   3200         self.classification.deferred.clone()
   3201     }
   3202 
   3203     fn retired_crates(&self) -> Vec<String> {
   3204         self.classification.retired.clone()
   3205     }
   3206 
   3207     fn yank_only_crates(&self) -> Vec<String> {
   3208         self.classification.yank_only.clone()
   3209     }
   3210 }
   3211 
   3212 fn parse_toml<T: for<'de> Deserialize<'de>>(path: &Path) -> Result<T, String> {
   3213     let raw = match fs::read_to_string(path) {
   3214         Ok(raw) => raw,
   3215         Err(e) => return Err(format!("read {}: {e}", path.display())),
   3216     };
   3217     match toml::from_str::<T>(&raw) {
   3218         Ok(parsed) => Ok(parsed),
   3219         Err(e) => Err(format!("parse {}: {e}", path.display())),
   3220     }
   3221 }
   3222 
   3223 fn parse_json<T: for<'de> Deserialize<'de>>(path: &Path) -> Result<T, String> {
   3224     let raw = match fs::read_to_string(path) {
   3225         Ok(raw) => raw,
   3226         Err(e) => return Err(format!("read {}: {e}", path.display())),
   3227     };
   3228     match serde_json::from_str::<T>(&raw) {
   3229         Ok(parsed) => Ok(parsed),
   3230         Err(e) => Err(format!("parse {}: {e}", path.display())),
   3231     }
   3232 }
   3233 
   3234 fn resolve_event_boundary_matrix_path(workspace_root: &Path) -> Result<PathBuf, String> {
   3235     let candidate = workspace_root.join(EVENT_BOUNDARY_MATRIX_RELATIVE);
   3236     if candidate.is_file() {
   3237         return Ok(candidate);
   3238     }
   3239     resolve_missing_event_boundary_matrix_path(workspace_root)
   3240 }
   3241 
   3242 fn missing_event_boundary_matrix_error() -> String {
   3243     format!("canonical event matrix not found at {EVENT_BOUNDARY_MATRIX_RELATIVE}")
   3244 }
   3245 
   3246 #[cfg(not(test))]
   3247 fn resolve_missing_event_boundary_matrix_path(_workspace_root: &Path) -> Result<PathBuf, String> {
   3248     Err(missing_event_boundary_matrix_error())
   3249 }
   3250 
   3251 #[cfg(test)]
   3252 #[cfg_attr(coverage_nightly, coverage(off))]
   3253 fn resolve_missing_event_boundary_matrix_path(workspace_root: &Path) -> Result<PathBuf, String> {
   3254     if !should_synthesize_owner_contracts_for_tests(workspace_root) {
   3255         return Err(missing_event_boundary_matrix_error());
   3256     }
   3257     let path = std::env::temp_dir().join(format!(
   3258         "radroots_xtask_event_boundary_{}.md",
   3259         std::process::id()
   3260     ));
   3261     fs::write(&path, synthetic_event_boundary_matrix())
   3262         .map_err(|e| format!("write {}: {e}", path.display()))?;
   3263     Ok(path)
   3264 }
   3265 
   3266 #[cfg(test)]
   3267 #[cfg_attr(coverage_nightly, coverage(off))]
   3268 fn synthetic_event_boundary_matrix() -> String {
   3269     let mut raw = String::from(
   3270         "# Event boundary matrix\n\n## Coverage matrix\n\n| Domain | Kind | Radroots Type | RPC Methods | Notes |\n| --- | --- | --- | --- | --- |\n",
   3271     );
   3272     for expectation in CANONICAL_EVENT_BOUNDARY_EXPECTATIONS {
   3273         raw.push_str(&format!(
   3274             "| {} | {} | {} | {} | synthetic test matrix |\n",
   3275             expectation.domain,
   3276             expectation.kind,
   3277             expectation.radroots_type,
   3278             expectation.rpc_methods.join(", ")
   3279         ));
   3280     }
   3281     raw.push('\n');
   3282     raw
   3283 }
   3284 
   3285 fn parse_event_boundary_matrix(path: &Path) -> Result<BTreeMap<String, EventBoundaryRow>, String> {
   3286     let raw = match fs::read_to_string(path) {
   3287         Ok(raw) => raw,
   3288         Err(e) => return Err(format!("read {}: {e}", path.display())),
   3289     };
   3290     let mut rows = BTreeMap::new();
   3291     let mut in_table = false;
   3292     for line in raw.lines() {
   3293         let trimmed = line.trim();
   3294         if trimmed == "| Domain | Kind | Radroots Type | RPC Methods | Notes |" {
   3295             in_table = true;
   3296             continue;
   3297         }
   3298         if !in_table {
   3299             continue;
   3300         }
   3301         if trimmed.is_empty() {
   3302             break;
   3303         }
   3304         if trimmed == "| --- | --- | --- | --- | --- |" {
   3305             continue;
   3306         }
   3307         if !trimmed.starts_with('|') {
   3308             break;
   3309         }
   3310         let columns = trimmed
   3311             .trim_matches('|')
   3312             .split('|')
   3313             .map(|part| part.trim())
   3314             .collect::<Vec<_>>();
   3315         if columns.len() != 5 {
   3316             return Err(format!(
   3317                 "canonical event matrix row in {} must have exactly 5 columns: {}",
   3318                 path.display(),
   3319                 trimmed
   3320             ));
   3321         }
   3322         let domain = columns[0].to_string();
   3323         if domain.is_empty() {
   3324             return Err(format!(
   3325                 "canonical event matrix row in {} must define a non-empty domain",
   3326                 path.display()
   3327             ));
   3328         }
   3329         let rpc_methods = columns[3]
   3330             .split(',')
   3331             .map(str::trim)
   3332             .filter(|item| !item.is_empty())
   3333             .map(|item| item.to_string())
   3334             .collect::<BTreeSet<_>>();
   3335         if rpc_methods.is_empty() {
   3336             return Err(format!(
   3337                 "canonical event matrix row {} in {} must define rpc methods",
   3338                 domain,
   3339                 path.display()
   3340             ));
   3341         }
   3342         let row = EventBoundaryRow {
   3343             domain: domain.clone(),
   3344             kind: columns[1].to_string(),
   3345             radroots_type: columns[2].to_string(),
   3346             rpc_methods,
   3347         };
   3348         if rows.insert(domain.clone(), row).is_some() {
   3349             return Err(format!(
   3350                 "canonical event matrix {} has duplicate domain row {}",
   3351                 path.display(),
   3352                 domain
   3353             ));
   3354         }
   3355     }
   3356 
   3357     if rows.is_empty() {
   3358         return Err(format!(
   3359             "canonical event matrix {} does not contain the coverage table",
   3360             path.display()
   3361         ));
   3362     }
   3363 
   3364     Ok(rows)
   3365 }
   3366 
   3367 fn validate_event_boundary_source_witness(
   3368     workspace_root: &Path,
   3369     domain: &str,
   3370     witness: &EventBoundarySourceWitness,
   3371 ) -> Result<(), String> {
   3372     let path = workspace_root.join(witness.relative_path);
   3373     let source = match fs::read_to_string(&path) {
   3374         Ok(source) => source,
   3375         Err(e) => return Err(format!("read {}: {e}", path.display())),
   3376     };
   3377     for fragment in witness.required_fragments {
   3378         if !source.contains(fragment) {
   3379             return Err(format!(
   3380                 "canonical event row {} is missing required implementation fragment {} in {}",
   3381                 domain,
   3382                 fragment,
   3383                 path.display()
   3384             ));
   3385         }
   3386     }
   3387     Ok(())
   3388 }
   3389 
   3390 fn validate_canonical_event_boundary_at_path(
   3391     workspace_root: &Path,
   3392     matrix_path: &Path,
   3393 ) -> Result<(), String> {
   3394     let rows = parse_event_boundary_matrix(matrix_path)?;
   3395     let expected_domains = CANONICAL_EVENT_BOUNDARY_EXPECTATIONS
   3396         .iter()
   3397         .map(|row| row.domain.to_string())
   3398         .collect::<BTreeSet<_>>();
   3399     let actual_domains = rows.keys().cloned().collect::<BTreeSet<_>>();
   3400     if actual_domains != expected_domains {
   3401         let missing = expected_domains
   3402             .difference(&actual_domains)
   3403             .cloned()
   3404             .collect::<BTreeSet<_>>();
   3405         let extra = actual_domains
   3406             .difference(&expected_domains)
   3407             .cloned()
   3408             .collect::<BTreeSet<_>>();
   3409         return Err(format!(
   3410             "canonical event matrix {} is missing rows: {}; and includes unexpected rows: {}",
   3411             matrix_path.display(),
   3412             join_set(&missing),
   3413             join_set(&extra)
   3414         ));
   3415     }
   3416 
   3417     for expectation in CANONICAL_EVENT_BOUNDARY_EXPECTATIONS {
   3418         let row = rows.get(expectation.domain).ok_or_else(|| {
   3419             format!(
   3420                 "canonical event matrix {} is missing required row {}",
   3421                 matrix_path.display(),
   3422                 expectation.domain
   3423             )
   3424         })?;
   3425         if row.kind != expectation.kind {
   3426             return Err(format!(
   3427                 "canonical event row {} kind drift: expected {}, got {}",
   3428                 expectation.domain, expectation.kind, row.kind
   3429             ));
   3430         }
   3431         if row.radroots_type != expectation.radroots_type {
   3432             return Err(format!(
   3433                 "canonical event row {} type drift: expected {}, got {}",
   3434                 expectation.domain, expectation.radroots_type, row.radroots_type
   3435             ));
   3436         }
   3437         let expected_methods = expectation
   3438             .rpc_methods
   3439             .iter()
   3440             .map(|method| (*method).to_string())
   3441             .collect::<BTreeSet<_>>();
   3442         if row.rpc_methods != expected_methods {
   3443             return Err(format!(
   3444                 "canonical event row {} rpc drift: expected {}, got {}",
   3445                 expectation.domain,
   3446                 join_set(&expected_methods),
   3447                 join_set(&row.rpc_methods)
   3448             ));
   3449         }
   3450         for witness in expectation.witnesses {
   3451             validate_event_boundary_source_witness(workspace_root, expectation.domain, witness)?;
   3452         }
   3453     }
   3454 
   3455     Ok(())
   3456 }
   3457 
   3458 pub fn validate_canonical_event_boundary(workspace_root: &Path) -> Result<(), String> {
   3459     let matrix_path = resolve_event_boundary_matrix_path(workspace_root)?;
   3460     validate_canonical_event_boundary_at_path(workspace_root, &matrix_path)
   3461 }
   3462 
   3463 fn contract_root(workspace_root: &Path) -> PathBuf {
   3464     workspace_root.join("contracts")
   3465 }
   3466 
   3467 fn conformance_root(workspace_root: &Path) -> PathBuf {
   3468     workspace_root.join(CONFORMANCE_ROOT_RELATIVE)
   3469 }
   3470 
   3471 fn conformance_schema_path(workspace_root: &Path) -> PathBuf {
   3472     workspace_root.join(CONFORMANCE_SCHEMA_RELATIVE)
   3473 }
   3474 
   3475 fn required_field_set(value: &Value, field: &str, path: &Path) -> Result<BTreeSet<String>, String> {
   3476     let required = value
   3477         .as_array()
   3478         .ok_or_else(|| format!("{field} in {} must be an array", path.display()))?;
   3479     let mut names = BTreeSet::new();
   3480     for item in required {
   3481         let name = item
   3482             .as_str()
   3483             .ok_or_else(|| format!("{field} in {} must contain strings", path.display()))?;
   3484         if name.trim().is_empty() {
   3485             return Err(format!(
   3486                 "{field} in {} must not contain empty names",
   3487                 path.display()
   3488             ));
   3489         }
   3490         names.insert(name.to_string());
   3491     }
   3492     Ok(names)
   3493 }
   3494 
   3495 fn validate_string_schema_property(
   3496     property: &Value,
   3497     field: &str,
   3498     path: &Path,
   3499     min_length: Option<u64>,
   3500     pattern: Option<&str>,
   3501 ) -> Result<(), String> {
   3502     let property = property
   3503         .as_object()
   3504         .ok_or_else(|| format!("{field} schema in {} must be an object", path.display()))?;
   3505     let kind = property
   3506         .get("type")
   3507         .and_then(Value::as_str)
   3508         .ok_or_else(|| format!("{field} schema in {} must declare type", path.display()))?;
   3509     if kind != "string" {
   3510         return Err(format!(
   3511             "{field} schema in {} must use type=string",
   3512             path.display()
   3513         ));
   3514     }
   3515     if let Some(expected) = min_length {
   3516         let actual = property
   3517             .get("minLength")
   3518             .and_then(Value::as_u64)
   3519             .ok_or_else(|| format!("{field} schema in {} must set minLength", path.display()))?;
   3520         if actual != expected {
   3521             return Err(format!(
   3522                 "{field} schema in {} must set minLength={expected}",
   3523                 path.display()
   3524             ));
   3525         }
   3526     }
   3527     if let Some(expected) = pattern {
   3528         let actual = property
   3529             .get("pattern")
   3530             .and_then(Value::as_str)
   3531             .ok_or_else(|| format!("{field} schema in {} must set pattern", path.display()))?;
   3532         if actual != expected {
   3533             return Err(format!(
   3534                 "{field} schema in {} must set pattern {}",
   3535                 path.display(),
   3536                 expected
   3537             ));
   3538         }
   3539     }
   3540     Ok(())
   3541 }
   3542 
   3543 fn validate_conformance_schema(workspace_root: &Path) -> Result<(), String> {
   3544     let path = conformance_schema_path(workspace_root);
   3545     let schema = parse_json::<Value>(&path)?;
   3546     let schema_obj = schema.as_object().ok_or_else(|| {
   3547         format!(
   3548             "conformance schema {} must be a JSON object",
   3549             path.display()
   3550         )
   3551     })?;
   3552     let schema_type = schema_obj
   3553         .get("type")
   3554         .and_then(Value::as_str)
   3555         .ok_or_else(|| format!("conformance schema {} must declare type", path.display()))?;
   3556     if schema_type != "object" {
   3557         return Err(format!(
   3558             "conformance schema {} must use type=object",
   3559             path.display()
   3560         ));
   3561     }
   3562     let additional = schema_obj
   3563         .get("additionalProperties")
   3564         .and_then(Value::as_bool)
   3565         .ok_or_else(|| {
   3566             format!(
   3567                 "conformance schema {} must declare additionalProperties",
   3568                 path.display()
   3569             )
   3570         })?;
   3571     if additional {
   3572         return Err(format!(
   3573             "conformance schema {} must disallow additionalProperties",
   3574             path.display()
   3575         ));
   3576     }
   3577     let root_required = required_field_set(
   3578         schema_obj.get("required").ok_or_else(|| {
   3579             format!(
   3580                 "conformance schema {} missing required list",
   3581                 path.display()
   3582             )
   3583         })?,
   3584         "required",
   3585         &path,
   3586     )?;
   3587     let expected_root_required = BTreeSet::from([
   3588         "suite".to_string(),
   3589         "contract_version".to_string(),
   3590         "vectors".to_string(),
   3591     ]);
   3592     if root_required != expected_root_required {
   3593         return Err(format!(
   3594             "conformance schema {} must require suite, contract_version, and vectors",
   3595             path.display()
   3596         ));
   3597     }
   3598     let properties = schema_obj
   3599         .get("properties")
   3600         .and_then(Value::as_object)
   3601         .ok_or_else(|| {
   3602             format!(
   3603                 "conformance schema {} missing properties map",
   3604                 path.display()
   3605             )
   3606         })?;
   3607     validate_string_schema_property(
   3608         properties.get("suite").ok_or_else(|| {
   3609             format!(
   3610                 "conformance schema {} missing suite property",
   3611                 path.display()
   3612             )
   3613         })?,
   3614         "suite",
   3615         &path,
   3616         Some(1),
   3617         None,
   3618     )?;
   3619     validate_string_schema_property(
   3620         properties.get("contract_version").ok_or_else(|| {
   3621             format!(
   3622                 "conformance schema {} missing contract_version property",
   3623                 path.display()
   3624             )
   3625         })?,
   3626         "contract_version",
   3627         &path,
   3628         None,
   3629         Some("^[0-9]+\\.[0-9]+\\.[0-9]+$"),
   3630     )?;
   3631     let vectors = properties
   3632         .get("vectors")
   3633         .and_then(Value::as_object)
   3634         .ok_or_else(|| {
   3635             format!(
   3636                 "conformance schema {} missing vectors property",
   3637                 path.display()
   3638             )
   3639         })?;
   3640     let vectors_type = vectors
   3641         .get("type")
   3642         .and_then(Value::as_str)
   3643         .ok_or_else(|| format!("vectors schema in {} must declare type", path.display()))?;
   3644     if vectors_type != "array" {
   3645         return Err(format!(
   3646             "vectors schema in {} must use type=array",
   3647             path.display()
   3648         ));
   3649     }
   3650     let items = vectors
   3651         .get("items")
   3652         .and_then(Value::as_object)
   3653         .ok_or_else(|| format!("vectors schema in {} must define items", path.display()))?;
   3654     let items_type = items
   3655         .get("type")
   3656         .and_then(Value::as_str)
   3657         .ok_or_else(|| format!("vector item schema in {} must declare type", path.display()))?;
   3658     if items_type != "object" {
   3659         return Err(format!(
   3660             "vector item schema in {} must use type=object",
   3661             path.display()
   3662         ));
   3663     }
   3664     let items_additional = items
   3665         .get("additionalProperties")
   3666         .and_then(Value::as_bool)
   3667         .ok_or_else(|| {
   3668             format!(
   3669                 "vector item schema in {} must declare additionalProperties",
   3670                 path.display()
   3671             )
   3672         })?;
   3673     if items_additional {
   3674         return Err(format!(
   3675             "vector item schema in {} must disallow additionalProperties",
   3676             path.display()
   3677         ));
   3678     }
   3679     let item_required = required_field_set(
   3680         items.get("required").ok_or_else(|| {
   3681             format!(
   3682                 "vector item schema in {} missing required list",
   3683                 path.display()
   3684             )
   3685         })?,
   3686         "required",
   3687         &path,
   3688     )?;
   3689     let expected_item_required =
   3690         BTreeSet::from(["id".to_string(), "input".to_string(), "kind".to_string()]);
   3691     if item_required != expected_item_required {
   3692         return Err(format!(
   3693             "vector item schema in {} must require id, kind, and input",
   3694             path.display()
   3695         ));
   3696     }
   3697     let expected_one_of = serde_json::json!([
   3698         {
   3699             "required": ["expected"],
   3700             "not": {"required": ["expected_error_contains"]}
   3701         },
   3702         {
   3703             "required": ["expected_error_contains"],
   3704             "not": {"required": ["expected"]}
   3705         }
   3706     ]);
   3707     if items.get("oneOf") != Some(&expected_one_of) {
   3708         return Err(format!(
   3709             "vector item schema in {} must require exactly one of expected or expected_error_contains",
   3710             path.display()
   3711         ));
   3712     }
   3713     let item_properties = items
   3714         .get("properties")
   3715         .and_then(Value::as_object)
   3716         .ok_or_else(|| {
   3717             format!(
   3718                 "vector item schema in {} missing properties",
   3719                 path.display()
   3720             )
   3721         })?;
   3722     validate_string_schema_property(
   3723         item_properties.get("id").ok_or_else(|| {
   3724             format!(
   3725                 "vector item schema in {} missing id property",
   3726                 path.display()
   3727             )
   3728         })?,
   3729         "id",
   3730         &path,
   3731         Some(1),
   3732         None,
   3733     )?;
   3734     validate_string_schema_property(
   3735         item_properties.get("kind").ok_or_else(|| {
   3736             format!(
   3737                 "vector item schema in {} missing kind property",
   3738                 path.display()
   3739             )
   3740         })?,
   3741         "kind",
   3742         &path,
   3743         Some(1),
   3744         None,
   3745     )?;
   3746     for field in ["input", "expected"] {
   3747         let property = item_properties.get(field).ok_or_else(|| {
   3748             format!(
   3749                 "vector item schema in {} missing {} property",
   3750                 path.display(),
   3751                 field
   3752             )
   3753         })?;
   3754         if !property.is_object() {
   3755             return Err(format!(
   3756                 "vector item schema in {} must define {} as an object schema",
   3757                 path.display(),
   3758                 field
   3759             ));
   3760         }
   3761     }
   3762     validate_string_schema_property(
   3763         item_properties
   3764             .get("expected_error_contains")
   3765             .ok_or_else(|| {
   3766                 format!(
   3767                     "vector item schema in {} missing expected_error_contains property",
   3768                     path.display()
   3769                 )
   3770             })?,
   3771         "expected_error_contains",
   3772         &path,
   3773         Some(1),
   3774         None,
   3775     )?;
   3776     Ok(())
   3777 }
   3778 
   3779 fn base_contract_version(version: &str) -> &str {
   3780     version.split_once('-').map_or(version, |(base, _)| base)
   3781 }
   3782 
   3783 fn parse_semver_version(version: &str) -> Result<Version, String> {
   3784     Version::parse(version)
   3785         .map_err(|error| format!("version {version} is not valid SemVer: {error}"))
   3786 }
   3787 
   3788 fn validate_contract_version_lockstep(bundle: &ContractBundle) -> Result<(), String> {
   3789     let contract_version = bundle.manifest.contract.version.as_str();
   3790     parse_semver_version(contract_version)?;
   3791     if bundle.version.contract.version != contract_version {
   3792         return Err(format!(
   3793             "version contract {} must match manifest contract version {}",
   3794             bundle.version.contract.version, contract_version
   3795         ));
   3796     }
   3797     if bundle.operations_manifest.contract.version != contract_version {
   3798         return Err(format!(
   3799             "operations contract version {} must match manifest contract version {}",
   3800             bundle.operations_manifest.contract.version, contract_version
   3801         ));
   3802     }
   3803     Ok(())
   3804 }
   3805 
   3806 fn validate_workspace_version_lockstep(
   3807     workspace_root: &Path,
   3808     contract_version: &str,
   3809 ) -> Result<(), String> {
   3810     let workspace_manifest =
   3811         parse_toml::<WorkspaceVersionCargoManifest>(&workspace_root.join("Cargo.toml"))?;
   3812     let architecture_path =
   3813         workspace_root.join("contracts/crates/release_v1/radroots_crates_release_v1.toml");
   3814     let governed_version = if architecture_path.is_file() {
   3815         parse_toml::<CratesReleaseArchitecture>(&architecture_path)?
   3816             .repositories
   3817             .lib
   3818             .version
   3819     } else {
   3820         contract_version.to_owned()
   3821     };
   3822     if workspace_manifest.workspace.package.version != governed_version {
   3823         return Err(format!(
   3824             "workspace.package.version {} must match library repository version {}",
   3825             workspace_manifest.workspace.package.version, governed_version
   3826         ));
   3827     }
   3828     let mut governed_packages = BTreeMap::new();
   3829     for member in &workspace_manifest.workspace.members {
   3830         let package_path = workspace_root.join(member).join("Cargo.toml");
   3831         let package = parse_toml::<VersionedPackageCargoManifest>(&package_path)?;
   3832         let expected_version = governed_version.as_str();
   3833         match package.package.version {
   3834             PackageVersionSource::Literal(ref version) if version == expected_version => {}
   3835             PackageVersionSource::Literal(version) => {
   3836                 return Err(format!(
   3837                     "workspace member {member} package version {version} must match governed version {expected_version}"
   3838                 ));
   3839             }
   3840             PackageVersionSource::Workspace { workspace } => {
   3841                 return Err(format!(
   3842                     "workspace member {member} must set an explicit package version {expected_version}, not version.workspace = {workspace}, so mounted path consumers preserve the governed package version"
   3843                 ));
   3844             }
   3845         }
   3846         governed_packages.insert(
   3847             member.clone(),
   3848             (package.package.name.clone(), expected_version.to_owned()),
   3849         );
   3850 
   3851         if package.package.name.starts_with("radroots_") {
   3852             let exact_requirement = format!("={expected_version}");
   3853             let dependency = workspace_manifest
   3854                 .workspace
   3855                 .dependencies
   3856                 .get(&package.package.name)
   3857                 .ok_or_else(|| {
   3858                     format!(
   3859                         "workspace dependency {} is required for member {member}",
   3860                         package.package.name
   3861                     )
   3862                 })?;
   3863             if dependency.path.as_deref() != Some(member.as_str()) {
   3864                 return Err(format!(
   3865                     "workspace dependency {} path must be {member}",
   3866                     package.package.name
   3867                 ));
   3868             }
   3869             if dependency.version.as_deref() != Some(exact_requirement.as_str()) {
   3870                 return Err(format!(
   3871                     "workspace dependency {} version must be the exact requirement {}",
   3872                     package.package.name, exact_requirement
   3873                 ));
   3874             }
   3875         }
   3876     }
   3877 
   3878     for (dependency_name, dependency) in &workspace_manifest.workspace.dependencies {
   3879         let Some(path) = dependency.path.as_deref() else {
   3880             continue;
   3881         };
   3882         let Some((_, expected_version)) = governed_packages.get(path) else {
   3883             continue;
   3884         };
   3885         let exact_requirement = format!("={expected_version}");
   3886         if dependency.version.as_deref() != Some(exact_requirement.as_str()) {
   3887             return Err(format!(
   3888                 "workspace path dependency {dependency_name} version must be the exact requirement {exact_requirement}"
   3889             ));
   3890         }
   3891     }
   3892 
   3893     validate_cargo_lock_version_lockstep(workspace_root, &governed_packages)
   3894 }
   3895 
   3896 fn validate_cargo_lock_version_lockstep(
   3897     workspace_root: &Path,
   3898     governed_packages: &BTreeMap<String, (String, String)>,
   3899 ) -> Result<(), String> {
   3900     let lock = parse_toml::<CargoLockManifest>(&workspace_root.join("Cargo.lock"))?;
   3901     for (member, (package_name, expected_version)) in governed_packages {
   3902         let workspace_entries = lock
   3903             .package
   3904             .iter()
   3905             .filter(|package| package.name == *package_name && package.source.is_none())
   3906             .collect::<Vec<_>>();
   3907         if workspace_entries.len() != 1 {
   3908             return Err(format!(
   3909                 "Cargo.lock must contain exactly one source-free entry for workspace member {member} ({package_name})"
   3910             ));
   3911         }
   3912         if workspace_entries[0].version != *expected_version {
   3913             return Err(format!(
   3914                 "Cargo.lock package {package_name} version {} must match governed version {expected_version}",
   3915                 workspace_entries[0].version
   3916             ));
   3917         }
   3918     }
   3919     Ok(())
   3920 }
   3921 
   3922 fn valid_release_change_id(value: &str) -> bool {
   3923     !value.is_empty()
   3924         && !value.starts_with('-')
   3925         && !value.ends_with('-')
   3926         && !value.contains("--")
   3927         && value
   3928             .bytes()
   3929             .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
   3930 }
   3931 
   3932 fn validate_release_record(
   3933     workspace_root: &Path,
   3934     contract_version: &str,
   3935     semver: &SemverRules,
   3936 ) -> Result<(), String> {
   3937     let current_version = parse_semver_version(contract_version)?;
   3938     let releases_root = workspace_root.join(RELEASES_ROOT_RELATIVE);
   3939     if !releases_root.is_dir() {
   3940         return Err(format!(
   3941             "release records directory {RELEASES_ROOT_RELATIVE} is required"
   3942         ));
   3943     }
   3944     let record_relative = format!("{RELEASES_ROOT_RELATIVE}/{contract_version}.toml");
   3945     let record = parse_toml::<ReleaseRecord>(&workspace_root.join(&record_relative))?;
   3946     if record.schema_version != 1 {
   3947         return Err(format!(
   3948             "release record {record_relative} schema_version must be 1"
   3949         ));
   3950     }
   3951     if record.release.version != contract_version {
   3952         return Err(format!(
   3953             "release record version {} must match contract version {contract_version}",
   3954             record.release.version
   3955         ));
   3956     }
   3957     let previous_version = parse_semver_version(&record.release.previous_version)?;
   3958     if record.release.previous_version == contract_version {
   3959         return Err("release.previous_version must differ from release.version".to_string());
   3960     }
   3961     if current_version <= previous_version {
   3962         return Err(format!(
   3963             "release version {contract_version} must be greater than previous version {}",
   3964             record.release.previous_version
   3965         ));
   3966     }
   3967     let contract_base_version = format!(
   3968         "{}.{}.{}",
   3969         current_version.major, current_version.minor, current_version.patch
   3970     );
   3971     if record.release.contract_base_version != contract_base_version {
   3972         return Err(format!(
   3973             "release.contract_base_version {} must match contract base version {}",
   3974             record.release.contract_base_version, contract_base_version
   3975         ));
   3976     }
   3977     if !matches!(
   3978         record.release.status.as_str(),
   3979         "unreleased" | "released" | "yanked"
   3980     ) {
   3981         return Err(format!(
   3982             "release.status {} must be unreleased, released, or yanked",
   3983             record.release.status
   3984         ));
   3985     }
   3986 
   3987     let mut expected_artifacts = vec![
   3988         (
   3989             record.artifacts.changelog.as_str(),
   3990             CHANGELOG_RELATIVE,
   3991             false,
   3992         ),
   3993         (
   3994             record.artifacts.manifest.as_str(),
   3995             "contracts/manifest.toml",
   3996             false,
   3997         ),
   3998         (
   3999             record.artifacts.operations.as_str(),
   4000             "contracts/operations.toml",
   4001             false,
   4002         ),
   4003         (
   4004             record.artifacts.replica.as_str(),
   4005             REPLICA_CONTRACT_RELATIVE,
   4006             false,
   4007         ),
   4008         (
   4009             record.artifacts.conformance.as_str(),
   4010             CONFORMANCE_ROOT_RELATIVE,
   4011             true,
   4012         ),
   4013         (
   4014             record.artifacts.publish_policy.as_str(),
   4015             RELEASE_POLICY_RELATIVE,
   4016             false,
   4017         ),
   4018     ];
   4019     if let Some(sqlite_runtime) = record.artifacts.sqlite_runtime.as_deref() {
   4020         expected_artifacts.push((sqlite_runtime, SQLITE_RUNTIME_CONTRACT_RELATIVE, false));
   4021     }
   4022     for (actual, expected, directory) in expected_artifacts {
   4023         if actual != expected {
   4024             return Err(format!(
   4025                 "release artifact path {actual} must use canonical path {expected}"
   4026             ));
   4027         }
   4028         let path = workspace_root.join(actual);
   4029         if directory && !path.is_dir() || !directory && !path.is_file() {
   4030             return Err(format!("release artifact {actual} does not exist"));
   4031         }
   4032     }
   4033 
   4034     if record.changes.is_empty() {
   4035         return Err("release record must contain at least one change".to_string());
   4036     }
   4037     let mut change_ids = BTreeSet::new();
   4038     let mut has_breaking_change = false;
   4039     let major_impacts = semver
   4040         .major_on
   4041         .iter()
   4042         .map(String::as_str)
   4043         .collect::<BTreeSet<_>>();
   4044     let minor_impacts = semver
   4045         .minor_on
   4046         .iter()
   4047         .map(String::as_str)
   4048         .collect::<BTreeSet<_>>();
   4049     let patch_impacts = semver
   4050         .patch_on
   4051         .iter()
   4052         .map(String::as_str)
   4053         .collect::<BTreeSet<_>>();
   4054     for change in &record.changes {
   4055         if !valid_release_change_id(&change.id) {
   4056             return Err(format!(
   4057                 "release change id {} must use lowercase kebab-case",
   4058                 change.id
   4059             ));
   4060         }
   4061         if !change_ids.insert(change.id.as_str()) {
   4062             return Err(format!(
   4063                 "release record has duplicate change id {}",
   4064                 change.id
   4065             ));
   4066         }
   4067         if !matches!(
   4068             change.classification.as_str(),
   4069             "breaking" | "feature" | "fix" | "deprecation" | "security" | "docs"
   4070         ) {
   4071             return Err(format!(
   4072                 "release change {} has unsupported classification {}",
   4073                 change.id, change.classification
   4074             ));
   4075         }
   4076         has_breaking_change |= change.classification == "breaking";
   4077         if change.semver_impacts.is_empty() {
   4078             return Err(format!(
   4079                 "release change {} must declare at least one exact semver impact",
   4080                 change.id
   4081             ));
   4082         }
   4083         let mut change_impacts = BTreeSet::new();
   4084         let mut has_major_impact = false;
   4085         let mut has_minor_impact = false;
   4086         let mut has_patch_impact = false;
   4087         for impact in &change.semver_impacts {
   4088             if !change_impacts.insert(impact.as_str()) {
   4089                 return Err(format!(
   4090                     "release change {} has duplicate semver impact {impact}",
   4091                     change.id
   4092                 ));
   4093             }
   4094             if major_impacts.contains(impact.as_str()) {
   4095                 has_major_impact = true;
   4096             } else if minor_impacts.contains(impact.as_str()) {
   4097                 has_minor_impact = true;
   4098             } else if patch_impacts.contains(impact.as_str()) {
   4099                 has_patch_impact = true;
   4100             } else {
   4101                 return Err(format!(
   4102                     "release change {} semver impact {impact} is not governed by contracts/version.toml",
   4103                     change.id
   4104                 ));
   4105             }
   4106         }
   4107         let classification_matches = if has_major_impact {
   4108             change.classification == "breaking"
   4109         } else if has_minor_impact {
   4110             matches!(change.classification.as_str(), "feature" | "deprecation")
   4111         } else if has_patch_impact {
   4112             matches!(change.classification.as_str(), "fix" | "security" | "docs")
   4113         } else {
   4114             false
   4115         };
   4116         if !classification_matches {
   4117             return Err(format!(
   4118                 "release change {} classification {} does not match its governed semver impacts",
   4119                 change.id, change.classification
   4120             ));
   4121         }
   4122         if change.summary.trim().is_empty() {
   4123             return Err(format!(
   4124                 "release change {} summary must not be empty",
   4125                 change.id
   4126             ));
   4127         }
   4128     }
   4129     if current_version.major != previous_version.major && !has_breaking_change {
   4130         return Err("a major version transition requires a breaking release change".to_string());
   4131     }
   4132 
   4133     let declares_registry_sqlite = change_ids.contains("registry-sqlite-provenance");
   4134     if declares_registry_sqlite != record.artifacts.sqlite_runtime.is_some() {
   4135         return Err(format!(
   4136             "release change registry-sqlite-provenance and artifact {SQLITE_RUNTIME_CONTRACT_RELATIVE} must be declared together"
   4137         ));
   4138     }
   4139     if declares_registry_sqlite {
   4140         validate_sqlite_runtime_contract(workspace_root)?;
   4141     }
   4142 
   4143     validate_changelog_release_notes(workspace_root, contract_version)
   4144 }
   4145 
   4146 fn validate_sqlite_runtime_contract(workspace_root: &Path) -> Result<(), String> {
   4147     const PACKAGE_NAME: &str = "libsqlite3-sys";
   4148     const PACKAGE_VERSION: &str = "0.37.0";
   4149     const PACKAGE_SOURCE: &str = "registry+https://github.com/rust-lang/crates.io-index";
   4150     const ACTIVATION_ROUTE: [&str; 3] = [
   4151         "radroots_event_store/sqlite",
   4152         "sqlx/sqlite-bundled",
   4153         "libsqlite3-sys/bundled",
   4154     ];
   4155     const FORBIDDEN_HIGH_LEVEL_DEPENDENCIES: [&str; 6] = [
   4156         "diesel", "refinery", "rusqlite", "sea-orm", "sqlite", "sqlite3",
   4157     ];
   4158     const TEMPORARY_DIRECT_DEPENDENCIES: [&str; 0] = [];
   4159 
   4160     let contract = parse_toml::<SqliteRuntimeContract>(
   4161         &workspace_root.join(SQLITE_RUNTIME_CONTRACT_RELATIVE),
   4162     )?;
   4163     if contract.schema_version != 2
   4164         || contract.package.name != PACKAGE_NAME
   4165         || contract.package.version != PACKAGE_VERSION
   4166         || contract.package.source != PACKAGE_SOURCE
   4167         || contract.activation.route != ACTIVATION_ROUTE
   4168         || contract.access.high_level_library != "sqlx"
   4169         || contract.access.native_linkage_owner != "sqlx"
   4170         || contract.access.native_linkage_package != PACKAGE_NAME
   4171         || contract.access.maximum_native_linkages != 1
   4172         || contract.access.forbidden_high_level_dependencies != FORBIDDEN_HIGH_LEVEL_DEPENDENCIES
   4173         || contract.sealed_native_adapter.owner_package != "radroots_service_sqlite"
   4174         || contract.sealed_native_adapter.relative_module
   4175             != "crates/service_sqlite/src/sqlite_native_backup.rs"
   4176         || contract.sealed_native_adapter.capability != "incremental_online_backup"
   4177         || contract.sealed_native_adapter.status != "active"
   4178         || contract.migration.owner != "rcld-rshr-045"
   4179         || contract.migration.status != "in_progress"
   4180         || contract.migration.temporary_direct_dependencies != TEMPORARY_DIRECT_DEPENDENCIES
   4181     {
   4182         return Err(format!(
   4183             "{SQLITE_RUNTIME_CONTRACT_RELATIVE} must govern the exact SQLx access, native SQLite linkage, sealed-adapter, and RCLD-045 migration policy"
   4184         ));
   4185     }
   4186     if contract.package.checksum.len() != 64
   4187         || !contract
   4188             .package
   4189             .checksum
   4190             .bytes()
   4191             .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
   4192     {
   4193         return Err(format!(
   4194             "{SQLITE_RUNTIME_CONTRACT_RELATIVE} package.checksum must be a lowercase SHA-256 digest"
   4195         ));
   4196     }
   4197 
   4198     let lock = parse_toml::<CargoLockManifest>(&workspace_root.join("Cargo.lock"))?;
   4199     let matches = lock
   4200         .package
   4201         .iter()
   4202         .filter(|package| {
   4203             package.name == contract.package.name
   4204                 && package.version == contract.package.version
   4205                 && package.source.as_deref() == Some(contract.package.source.as_str())
   4206                 && package.checksum.as_deref() == Some(contract.package.checksum.as_str())
   4207         })
   4208         .count();
   4209     if matches != 1 {
   4210         return Err(format!(
   4211             "Cargo.lock must contain exactly one package matching {SQLITE_RUNTIME_CONTRACT_RELATIVE}"
   4212         ));
   4213     }
   4214 
   4215     let native_linkages = lock
   4216         .package
   4217         .iter()
   4218         .filter(|package| package.name == contract.access.native_linkage_package)
   4219         .count();
   4220     if native_linkages != contract.access.maximum_native_linkages as usize {
   4221         return Err(format!(
   4222             "Cargo.lock must contain exactly {} {} native linkage",
   4223             contract.access.maximum_native_linkages, contract.access.native_linkage_package
   4224         ));
   4225     }
   4226 
   4227     let workspace = parse_toml::<WorkspaceCargoManifest>(&workspace_root.join("Cargo.toml"))?;
   4228     for member in &workspace.workspace.members {
   4229         let package =
   4230             parse_toml::<PackageCargoManifest>(&workspace_root.join(member).join("Cargo.toml"))?;
   4231         if package.package.name == PACKAGE_NAME {
   4232             return Err(format!(
   4233                 "workspace member {member} must not vendor registry package {PACKAGE_NAME}"
   4234             ));
   4235         }
   4236     }
   4237 
   4238     let actual_temporary = sqlite_forbidden_direct_dependencies(
   4239         workspace_root,
   4240         &workspace.workspace.members,
   4241         &contract.access.forbidden_high_level_dependencies,
   4242     )?;
   4243     let expected_temporary = contract
   4244         .migration
   4245         .temporary_direct_dependencies
   4246         .iter()
   4247         .cloned()
   4248         .collect::<BTreeSet<_>>();
   4249     if actual_temporary != expected_temporary {
   4250         return Err(format!(
   4251             "{SQLITE_RUNTIME_CONTRACT_RELATIVE} temporary direct dependency inventory is stale: expected {expected_temporary:?}, found {actual_temporary:?}"
   4252         ));
   4253     }
   4254 
   4255     let direct_native_dependencies = sqlite_direct_dependency_owners(
   4256         workspace_root,
   4257         &workspace.workspace.members,
   4258         PACKAGE_NAME,
   4259     )?;
   4260     let expected_direct_native_dependencies = BTreeSet::from([
   4261         "radroots_service_sqlite:libsqlite3-sys".to_owned(),
   4262         "workspace:libsqlite3-sys".to_owned(),
   4263     ]);
   4264     if direct_native_dependencies != expected_direct_native_dependencies {
   4265         return Err(format!(
   4266             "direct {PACKAGE_NAME} access must be limited to the sealed adapter owner: expected {expected_direct_native_dependencies:?}, found {direct_native_dependencies:?}"
   4267         ));
   4268     }
   4269     validate_sqlite_native_adapter_source(workspace_root, &contract.sealed_native_adapter)?;
   4270 
   4271     let storage_sqlite =
   4272         fs::read_to_string(workspace_root.join("crates/storage_sqlite/Cargo.toml"))
   4273             .map_err(|error| format!("read crates/storage_sqlite/Cargo.toml: {error}"))?;
   4274     let storage_sqlite: toml::Value = toml::from_str(&storage_sqlite)
   4275         .map_err(|error| format!("parse crates/storage_sqlite/Cargo.toml: {error}"))?;
   4276     let sqlite_features = storage_sqlite
   4277         .get("dependencies")
   4278         .and_then(|dependencies| dependencies.get("sqlx"))
   4279         .and_then(|sqlx| sqlx.get("features"))
   4280         .and_then(toml::Value::as_array)
   4281         .ok_or_else(|| {
   4282             "crates/storage_sqlite/Cargo.toml dependencies.sqlx.features is required".to_string()
   4283         })?;
   4284     if !sqlite_features
   4285         .iter()
   4286         .any(|feature| feature.as_str() == Some("sqlite-bundled"))
   4287     {
   4288         return Err(
   4289             "crates/storage_sqlite/Cargo.toml dependencies.sqlx.features must activate sqlite-bundled"
   4290                 .to_string(),
   4291         );
   4292     }
   4293     Ok(())
   4294 }
   4295 
   4296 fn validate_sqlite_native_adapter_source(
   4297     workspace_root: &Path,
   4298     adapter: &SqliteRuntimeSealedNativeAdapter,
   4299 ) -> Result<(), String> {
   4300     let adapter_path = workspace_root.join(&adapter.relative_module);
   4301     let adapter_source = fs::read_to_string(&adapter_path)
   4302         .map_err(|error| format!("read {}: {error}", adapter_path.display()))?;
   4303     for required in [
   4304         "use libsqlite3_sys as ffi;",
   4305         "LockedSqliteHandle",
   4306         "ffi::sqlite3_backup_init",
   4307         "ffi::sqlite3_backup_step",
   4308         "ffi::sqlite3_backup_finish",
   4309     ] {
   4310         if !adapter_source.contains(required) {
   4311             return Err(format!(
   4312                 "{} must contain the sealed native adapter boundary `{required}`",
   4313                 adapter_path.display()
   4314             ));
   4315         }
   4316     }
   4317 
   4318     let source_root = workspace_root.join("crates/service_sqlite/src");
   4319     for entry in WalkDir::new(&source_root).follow_links(false) {
   4320         let entry = entry.map_err(|error| format!("walk {}: {error}", source_root.display()))?;
   4321         if !entry.file_type().is_file()
   4322             || entry
   4323                 .path()
   4324                 .extension()
   4325                 .and_then(|extension| extension.to_str())
   4326                 != Some("rs")
   4327             || entry.path() == adapter_path
   4328         {
   4329             continue;
   4330         }
   4331         let source = fs::read_to_string(entry.path())
   4332             .map_err(|error| format!("read {}: {error}", entry.path().display()))?;
   4333         for forbidden in [
   4334             "libsqlite3_sys",
   4335             "sqlite3_backup_",
   4336             "unsafe {",
   4337             "unsafe fn ",
   4338             "unsafe impl ",
   4339         ] {
   4340             if source.contains(forbidden) {
   4341                 return Err(format!(
   4342                     "{} contains native SQLite or unsafe authority outside the sealed adapter: `{forbidden}`",
   4343                     entry.path().display()
   4344                 ));
   4345             }
   4346         }
   4347     }
   4348     Ok(())
   4349 }
   4350 
   4351 fn sqlite_forbidden_direct_dependencies(
   4352     workspace_root: &Path,
   4353     members: &[String],
   4354     forbidden: &[String],
   4355 ) -> Result<BTreeSet<String>, String> {
   4356     let forbidden = forbidden
   4357         .iter()
   4358         .map(String::as_str)
   4359         .collect::<BTreeSet<_>>();
   4360     sqlite_direct_dependencies_matching(workspace_root, members, |dependency| {
   4361         forbidden.contains(dependency)
   4362     })
   4363 }
   4364 
   4365 fn sqlite_direct_dependency_owners(
   4366     workspace_root: &Path,
   4367     members: &[String],
   4368     dependency: &str,
   4369 ) -> Result<BTreeSet<String>, String> {
   4370     sqlite_direct_dependencies_matching(workspace_root, members, |candidate| {
   4371         candidate == dependency
   4372     })
   4373 }
   4374 
   4375 fn sqlite_direct_dependencies_matching(
   4376     workspace_root: &Path,
   4377     members: &[String],
   4378     matches: impl Fn(&str) -> bool,
   4379 ) -> Result<BTreeSet<String>, String> {
   4380     let mut found = BTreeSet::new();
   4381     let workspace_manifest = parse_toml::<toml::Value>(&workspace_root.join("Cargo.toml"))?;
   4382     if let Some(dependencies) = workspace_manifest
   4383         .get("workspace")
   4384         .and_then(|workspace| workspace.get("dependencies"))
   4385         .and_then(toml::Value::as_table)
   4386     {
   4387         collect_matching_dependencies("workspace", dependencies, &matches, &mut found);
   4388     }
   4389 
   4390     for member in members {
   4391         let path = workspace_root.join(member).join("Cargo.toml");
   4392         let manifest = parse_toml::<toml::Value>(&path)?;
   4393         let owner = manifest
   4394             .get("package")
   4395             .and_then(|package| package.get("name"))
   4396             .and_then(toml::Value::as_str)
   4397             .ok_or_else(|| format!("{} package.name is required", path.display()))?;
   4398         for section in ["dependencies", "dev-dependencies", "build-dependencies"] {
   4399             if let Some(dependencies) = manifest.get(section).and_then(toml::Value::as_table) {
   4400                 collect_matching_dependencies(owner, dependencies, &matches, &mut found);
   4401             }
   4402         }
   4403         if let Some(targets) = manifest.get("target").and_then(toml::Value::as_table) {
   4404             for target in targets.values().filter_map(toml::Value::as_table) {
   4405                 for section in ["dependencies", "dev-dependencies", "build-dependencies"] {
   4406                     if let Some(dependencies) = target.get(section).and_then(toml::Value::as_table)
   4407                     {
   4408                         collect_matching_dependencies(owner, dependencies, &matches, &mut found);
   4409                     }
   4410                 }
   4411             }
   4412         }
   4413     }
   4414     Ok(found)
   4415 }
   4416 
   4417 fn collect_matching_dependencies(
   4418     owner: &str,
   4419     dependencies: &toml::map::Map<String, toml::Value>,
   4420     matches: &impl Fn(&str) -> bool,
   4421     found: &mut BTreeSet<String>,
   4422 ) {
   4423     for (alias, specification) in dependencies {
   4424         let package = specification
   4425             .as_table()
   4426             .and_then(|table| table.get("package"))
   4427             .and_then(toml::Value::as_str)
   4428             .unwrap_or(alias);
   4429         if matches(package) {
   4430             found.insert(format!("{owner}:{package}"));
   4431         }
   4432     }
   4433 }
   4434 
   4435 fn validate_changelog_release_notes(
   4436     workspace_root: &Path,
   4437     contract_version: &str,
   4438 ) -> Result<(), String> {
   4439     let path = workspace_root.join(CHANGELOG_RELATIVE);
   4440     let raw =
   4441         fs::read_to_string(&path).map_err(|error| format!("read {}: {error}", path.display()))?;
   4442     let heading = format!("## [{contract_version}]");
   4443     let mut in_release = false;
   4444     let mut has_release_note = false;
   4445     for line in raw.lines() {
   4446         let trimmed = line.trim();
   4447         if trimmed == heading {
   4448             if in_release {
   4449                 return Err(format!(
   4450                     "{CHANGELOG_RELATIVE} contains duplicate heading {heading}"
   4451                 ));
   4452             }
   4453             in_release = true;
   4454             continue;
   4455         }
   4456         if in_release && trimmed.starts_with("## [") {
   4457             break;
   4458         }
   4459         if in_release && trimmed.starts_with("- ") && trimmed.len() > 2 {
   4460             has_release_note = true;
   4461         }
   4462     }
   4463     if !in_release {
   4464         return Err(format!("{CHANGELOG_RELATIVE} is missing heading {heading}"));
   4465     }
   4466     if !has_release_note {
   4467         return Err(format!(
   4468             "{CHANGELOG_RELATIVE} release {contract_version} must contain at least one note"
   4469         ));
   4470     }
   4471     Ok(())
   4472 }
   4473 
   4474 fn validate_conformance_vector_mirrors(workspace_root: &Path) -> Result<(), String> {
   4475     for (canonical_relative, mirror_relative) in CONFORMANCE_VECTOR_MIRRORS {
   4476         let canonical = fs::read(workspace_root.join(canonical_relative))
   4477             .map_err(|error| format!("read {canonical_relative}: {error}"))?;
   4478         let mirror = fs::read(workspace_root.join(mirror_relative))
   4479             .map_err(|error| format!("read {mirror_relative}: {error}"))?;
   4480         if canonical != mirror {
   4481             return Err(format!(
   4482                 "packaged conformance mirror {mirror_relative} must exactly match {canonical_relative}"
   4483             ));
   4484         }
   4485     }
   4486     Ok(())
   4487 }
   4488 
   4489 fn validate_version_governance(
   4490     bundle: &ContractBundle,
   4491     workspace_root: &Path,
   4492 ) -> Result<(), String> {
   4493     validate_contract_version_lockstep(bundle)?;
   4494     let version = bundle.manifest.contract.version.as_str();
   4495     validate_workspace_version_lockstep(workspace_root, version)?;
   4496     validate_release_record(workspace_root, version, &bundle.version.semver)?;
   4497     validate_conformance_vector_mirrors(workspace_root)
   4498 }
   4499 
   4500 fn collect_conformance_vector_paths(dir: &Path, paths: &mut Vec<PathBuf>) -> Result<(), String> {
   4501     let read_dir = match fs::read_dir(dir) {
   4502         Ok(read_dir) => read_dir,
   4503         Err(e) => return Err(format!("read dir {}: {e}", dir.display())),
   4504     };
   4505     let mut entries = read_dir.filter_map(Result::ok).collect::<Vec<_>>();
   4506     entries.sort_by_key(|entry| entry.file_name());
   4507     for entry in entries {
   4508         let path = entry.path();
   4509         if path.is_dir() {
   4510             collect_conformance_vector_paths(&path, paths)?;
   4511         } else if path.extension().and_then(|ext| ext.to_str()) == Some("json") {
   4512             paths.push(path);
   4513         }
   4514     }
   4515     Ok(())
   4516 }
   4517 
   4518 fn validate_conformance_vector_file(
   4519     path: &Path,
   4520     contract_version: &str,
   4521 ) -> Result<ConformanceVectorFile, String> {
   4522     let vector = parse_json::<ConformanceVectorFile>(path)?;
   4523     if vector.suite.trim().is_empty() {
   4524         return Err(format!(
   4525             "conformance vector {} suite must not be empty",
   4526             path.display()
   4527         ));
   4528     }
   4529     if vector.vectors.is_empty() {
   4530         return Err(format!(
   4531             "conformance vector {} must contain at least one vector",
   4532             path.display()
   4533         ));
   4534     }
   4535     if vector.contract_version != base_contract_version(contract_version) {
   4536         return Err(format!(
   4537             "conformance vector {} version {} must match contract version {}",
   4538             path.display(),
   4539             vector.contract_version,
   4540             base_contract_version(contract_version)
   4541         ));
   4542     }
   4543     let mut ids = BTreeSet::new();
   4544     for entry in &vector.vectors {
   4545         if entry.id.trim().is_empty() || entry.kind.trim().is_empty() {
   4546             return Err(format!(
   4547                 "conformance vector {} entries must define non-empty id and kind",
   4548                 path.display()
   4549             ));
   4550         }
   4551         if !ids.insert(entry.id.clone()) {
   4552             return Err(format!(
   4553                 "conformance vector {} has duplicate vector id {}",
   4554                 path.display(),
   4555                 entry.id
   4556             ));
   4557         }
   4558         match (&entry.expected, &entry.expected_error_contains) {
   4559             (Some(_), None) => {}
   4560             (None, Some(fragment)) if !fragment.trim().is_empty() => {}
   4561             (None, Some(_)) => {
   4562                 return Err(format!(
   4563                     "conformance vector {} entry {} expected_error_contains must not be blank",
   4564                     path.display(),
   4565                     entry.id
   4566                 ));
   4567             }
   4568             _ => {
   4569                 return Err(format!(
   4570                     "conformance vector {} entry {} must define exactly one of expected or expected_error_contains",
   4571                     path.display(),
   4572                     entry.id
   4573                 ));
   4574             }
   4575         }
   4576     }
   4577     Ok(vector)
   4578 }
   4579 
   4580 fn validate_all_conformance_vectors(
   4581     workspace_root: &Path,
   4582     contract_version: &str,
   4583 ) -> Result<(), String> {
   4584     let vectors_dir = conformance_root(workspace_root).join("vectors");
   4585     if !vectors_dir.is_dir() {
   4586         return validate_missing_conformance_vectors(workspace_root, &vectors_dir);
   4587     }
   4588     let mut paths = Vec::new();
   4589     collect_conformance_vector_paths(&vectors_dir, &mut paths)?;
   4590     if paths.is_empty() {
   4591         return Err(format!(
   4592             "conformance vectors directory {} must contain JSON vectors",
   4593             vectors_dir.display()
   4594         ));
   4595     }
   4596     let canonical_comment_path = workspace_root.join(COMMENT_CONFORMANCE_VECTOR_RELATIVE);
   4597     let canonical_deletion_path = workspace_root.join(DELETION_CONFORMANCE_VECTOR_RELATIVE);
   4598     let canonical_deletion_suppression_path =
   4599         workspace_root.join(DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE);
   4600     for path in paths {
   4601         let vector = validate_conformance_vector_file(&path, contract_version)?;
   4602         validate_comment_vector_namespace(&path, &canonical_comment_path, &vector)?;
   4603         validate_deletion_vector_namespace(
   4604             &path,
   4605             &canonical_deletion_path,
   4606             &canonical_deletion_suppression_path,
   4607             &vector,
   4608         )?;
   4609     }
   4610     Ok(())
   4611 }
   4612 
   4613 fn validate_deletion_vector_namespace(
   4614     path: &Path,
   4615     canonical_request_path: &Path,
   4616     canonical_suppression_path: &Path,
   4617     vector: &ConformanceVectorFile,
   4618 ) -> Result<(), String> {
   4619     if path == canonical_request_path || path == canonical_suppression_path {
   4620         return Ok(());
   4621     }
   4622     if let Some(entry) = vector
   4623         .vectors
   4624         .iter()
   4625         .find(|entry| entry.kind.starts_with("social.deletion_request."))
   4626     {
   4627         return Err(format!(
   4628             "deletion conformance case kind {} in {} is outside canonical vectors {} and {}",
   4629             entry.kind,
   4630             path.display(),
   4631             canonical_request_path.display(),
   4632             canonical_suppression_path.display()
   4633         ));
   4634     }
   4635     Ok(())
   4636 }
   4637 
   4638 fn validate_comment_vector_namespace(
   4639     path: &Path,
   4640     canonical_path: &Path,
   4641     vector: &ConformanceVectorFile,
   4642 ) -> Result<(), String> {
   4643     if path == canonical_path {
   4644         return Ok(());
   4645     }
   4646     if let Some(entry) = vector
   4647         .vectors
   4648         .iter()
   4649         .find(|entry| entry.kind.starts_with("social.comment."))
   4650     {
   4651         return Err(format!(
   4652             "comment conformance case kind {} in {} is outside canonical vector {}",
   4653             entry.kind,
   4654             path.display(),
   4655             canonical_path.display()
   4656         ));
   4657     }
   4658     Ok(())
   4659 }
   4660 
   4661 pub fn write_knowledge_contract_manifest(workspace_root: &Path) -> Result<(), String> {
   4662     let manifest_json = write_knowledge_contract_manifest_artifacts(workspace_root)?;
   4663     validate_knowledge_contract_manifest_context(workspace_root, &manifest_json)
   4664 }
   4665 
   4666 pub fn validate_knowledge_contract_manifest(workspace_root: &Path) -> Result<(), String> {
   4667     let manifest_json = validate_knowledge_contract_manifest_artifacts(workspace_root)?;
   4668     validate_knowledge_contract_manifest_context(workspace_root, &manifest_json)
   4669 }
   4670 
   4671 fn write_knowledge_contract_manifest_artifacts(workspace_root: &Path) -> Result<String, String> {
   4672     with_artifact_bundle_transaction(workspace_root, |transaction| {
   4673         let manifest_json = expected_knowledge_contract_manifest_json()?;
   4674         let manifest_sha256 = expected_knowledge_contract_manifest_sha256()?;
   4675         transaction.write(vec![
   4676             GeneratedArtifact {
   4677                 relative: KNOWLEDGE_MANIFEST_RELATIVE,
   4678                 contents: manifest_json.into_bytes(),
   4679             },
   4680             GeneratedArtifact {
   4681                 relative: KNOWLEDGE_MANIFEST_SHA256_RELATIVE,
   4682                 contents: format!("{manifest_sha256}\n").into_bytes(),
   4683             },
   4684         ])?;
   4685         validate_knowledge_contract_manifest_artifacts_under_lock(workspace_root)
   4686     })
   4687 }
   4688 
   4689 fn validate_knowledge_contract_manifest_artifacts(workspace_root: &Path) -> Result<String, String> {
   4690     with_artifact_bundle_transaction(workspace_root, |_| {
   4691         validate_knowledge_contract_manifest_artifacts_under_lock(workspace_root)
   4692     })
   4693 }
   4694 
   4695 fn validate_knowledge_contract_manifest_artifacts_under_lock(
   4696     workspace_root: &Path,
   4697 ) -> Result<String, String> {
   4698     let expected_json = expected_knowledge_contract_manifest_json()?;
   4699     let expected_sha256 = expected_knowledge_contract_manifest_sha256()?;
   4700     let actual_json = read_regular_file(workspace_root, KNOWLEDGE_MANIFEST_RELATIVE)?;
   4701     let actual_sha256 = read_regular_file(workspace_root, KNOWLEDGE_MANIFEST_SHA256_RELATIVE)?;
   4702     let actual_json_text = std::str::from_utf8(&actual_json)
   4703         .map_err(|error| format!("{KNOWLEDGE_MANIFEST_RELATIVE} must be UTF-8 JSON: {error}"))?;
   4704     let parsed =
   4705         radroots_event_codec::manifest::parse_knowledge_contract_manifest_json(actual_json_text)
   4706             .map_err(|error| format!("parse {KNOWLEDGE_MANIFEST_RELATIVE}: {error}"))?;
   4707 
   4708     validate_knowledge_contract_manifest_shape(&parsed)?;
   4709     validate_canonical_json_artifact(KNOWLEDGE_MANIFEST_RELATIVE, &actual_json)?;
   4710     validate_sha256_artifact(KNOWLEDGE_MANIFEST_SHA256_RELATIVE, &actual_sha256)?;
   4711 
   4712     if actual_json != expected_json.as_bytes() {
   4713         return Err(stale_knowledge_manifest_error(KNOWLEDGE_MANIFEST_RELATIVE));
   4714     }
   4715     if actual_sha256 != format!("{expected_sha256}\n").as_bytes() {
   4716         return Err(stale_knowledge_manifest_error(
   4717             KNOWLEDGE_MANIFEST_SHA256_RELATIVE,
   4718         ));
   4719     }
   4720     if parsed != radroots_event_codec::manifest::knowledge_contract_manifest() {
   4721         return Err(stale_knowledge_manifest_error(KNOWLEDGE_MANIFEST_RELATIVE));
   4722     }
   4723 
   4724     Ok(actual_json_text.to_owned())
   4725 }
   4726 
   4727 fn expected_knowledge_contract_manifest_json() -> Result<String, String> {
   4728     let expected_json = radroots_event_codec::manifest::contract_manifest_json()
   4729         .map_err(|error| format!("serialize knowledge contract manifest: {error}"))?;
   4730     Ok(expected_json)
   4731 }
   4732 
   4733 fn expected_knowledge_contract_manifest_sha256() -> Result<String, String> {
   4734     radroots_event_codec::manifest::contract_manifest_sha256()
   4735         .map_err(|error| format!("hash knowledge contract manifest: {error}"))
   4736 }
   4737 
   4738 fn validate_knowledge_contract_manifest_shape(
   4739     manifest: &radroots_event_codec::manifest::RadrootsKnowledgeContractManifest,
   4740 ) -> Result<(), String> {
   4741     if manifest.schema_version
   4742         != radroots_event_codec::manifest::RADROOTS_KNOWLEDGE_CONTRACT_MANIFEST_SCHEMA_VERSION
   4743     {
   4744         return Err(format!(
   4745             "{KNOWLEDGE_MANIFEST_RELATIVE} schema_version must be {}",
   4746             radroots_event_codec::manifest::RADROOTS_KNOWLEDGE_CONTRACT_MANIFEST_SCHEMA_VERSION
   4747         ));
   4748     }
   4749     if manifest.registry_version
   4750         != radroots_event_codec::manifest::registry_v7::RADROOTS_EVENT_CONTRACT_REGISTRY_V7_VERSION
   4751     {
   4752         return Err(format!(
   4753             "{KNOWLEDGE_MANIFEST_RELATIVE} registry_version must be {}",
   4754             radroots_event_codec::manifest::registry_v7::RADROOTS_EVENT_CONTRACT_REGISTRY_V7_VERSION
   4755         ));
   4756     }
   4757     if manifest.contract_count != manifest.contracts.len() {
   4758         return Err(format!(
   4759             "{KNOWLEDGE_MANIFEST_RELATIVE} contract_count must match its contract inventory"
   4760         ));
   4761     }
   4762     if manifest
   4763         .contracts
   4764         .windows(2)
   4765         .any(|pair| pair[0].contract_id >= pair[1].contract_id)
   4766     {
   4767         return Err(format!(
   4768             "{KNOWLEDGE_MANIFEST_RELATIVE} contract IDs must be unique and strictly sorted"
   4769         ));
   4770     }
   4771     Ok(())
   4772 }
   4773 
   4774 fn stale_knowledge_manifest_error(relative: &str) -> String {
   4775     format!("{relative} is stale; run `{KNOWLEDGE_MANIFEST_WRITE_COMMAND}`")
   4776 }
   4777 
   4778 fn validate_knowledge_contract_manifest_context(
   4779     workspace_root: &Path,
   4780     manifest_json: &str,
   4781 ) -> Result<(), String> {
   4782     validate_knowledge_manifest_witnesses(workspace_root, manifest_json)?;
   4783     validate_knowledge_conformance_vector_inventory(workspace_root)?;
   4784 
   4785     let bundle = load_contract_bundle(workspace_root)?;
   4786     let knowledge_manifest_vector = validate_conformance_vector_file(
   4787         &workspace_root.join(KNOWLEDGE_MANIFEST_AND_DECODE_RELATIVE),
   4788         &bundle.manifest.contract.version,
   4789     )?;
   4790     validate_knowledge_manifest_vector_semantics(manifest_json, &knowledge_manifest_vector)?;
   4791     validate_conformance_vector_file(
   4792         &workspace_root.join(KNOWLEDGE_PUBLIC_SURFACE_RELATIVE),
   4793         &bundle.manifest.contract.version,
   4794     )?;
   4795     Ok(())
   4796 }
   4797 
   4798 fn validate_knowledge_manifest_vector_semantics(
   4799     manifest_json: &str,
   4800     vector: &ConformanceVectorFile,
   4801 ) -> Result<(), String> {
   4802     let manifest = serde_json::from_str::<Value>(manifest_json)
   4803         .map_err(|error| format!("parse knowledge manifest JSON: {error}"))?;
   4804     let schema_version = manifest
   4805         .get("schema_version")
   4806         .and_then(Value::as_u64)
   4807         .ok_or_else(|| {
   4808             "knowledge manifest schema_version must be an unsigned integer".to_string()
   4809         })?;
   4810     let registry_version = manifest
   4811         .get("registry_version")
   4812         .and_then(Value::as_u64)
   4813         .ok_or_else(|| {
   4814             "knowledge manifest registry_version must be an unsigned integer".to_string()
   4815         })?;
   4816     let case = vector
   4817         .vectors
   4818         .iter()
   4819         .find(|entry| entry.id == "knowledge_manifest_fields_valid_001")
   4820         .ok_or_else(|| {
   4821             "knowledge manifest conformance must define knowledge_manifest_fields_valid_001"
   4822                 .to_string()
   4823         })?;
   4824     if case.kind != "knowledge.contract_manifest_json.valid" {
   4825         return Err(format!(
   4826             "knowledge manifest conformance case kind drift: expected knowledge.contract_manifest_json.valid, got {}",
   4827             case.kind
   4828         ));
   4829     }
   4830 
   4831     let expected_registry_marker = format!("radroots_event_contract_registry_v{registry_version}");
   4832     let actual_registry_marker = case.input.get("registry").and_then(Value::as_str);
   4833     if actual_registry_marker != Some(expected_registry_marker.as_str()) {
   4834         return Err(format!(
   4835             "knowledge manifest conformance registry marker drift: expected {expected_registry_marker}, got {}",
   4836             actual_registry_marker.unwrap_or("<missing-or-non-string>")
   4837         ));
   4838     }
   4839 
   4840     for (field, expected) in [
   4841         ("schema_version", schema_version),
   4842         ("registry_version", registry_version),
   4843     ] {
   4844         let actual = case.expected_value()?.get(field).and_then(Value::as_u64);
   4845         if actual != Some(expected) {
   4846             return Err(format!(
   4847                 "knowledge manifest conformance expected {field} drift: expected {expected}, got {}",
   4848                 actual
   4849                     .map(|value| value.to_string())
   4850                     .unwrap_or_else(|| "<missing-or-non-integer>".to_string())
   4851             ));
   4852         }
   4853     }
   4854     Ok(())
   4855 }
   4856 
   4857 fn validate_knowledge_conformance_vector_inventory(workspace_root: &Path) -> Result<(), String> {
   4858     let expected = BTreeSet::from([
   4859         KNOWLEDGE_MANIFEST_AND_DECODE_RELATIVE.to_owned(),
   4860         KNOWLEDGE_PUBLIC_SURFACE_RELATIVE.to_owned(),
   4861     ]);
   4862     let mut paths = Vec::new();
   4863     collect_conformance_vector_paths(
   4864         &workspace_root.join("contracts/conformance/vectors/knowledge"),
   4865         &mut paths,
   4866     )?;
   4867     let mut actual = BTreeSet::new();
   4868     for path in paths {
   4869         let relative = path.strip_prefix(workspace_root).map_err(|error| {
   4870             format!(
   4871                 "knowledge conformance vector {} is outside workspace root {}: {error}",
   4872                 path.display(),
   4873                 workspace_root.display()
   4874             )
   4875         })?;
   4876         actual.insert(relative.to_string_lossy().replace('\\', "/"));
   4877     }
   4878     if actual != expected {
   4879         return Err(format!(
   4880             "knowledge conformance vector inventory mismatch: expected {:?}, found {:?}",
   4881             expected, actual
   4882         ));
   4883     }
   4884     Ok(())
   4885 }
   4886 
   4887 fn validate_knowledge_manifest_witnesses(
   4888     workspace_root: &Path,
   4889     actual_json: &str,
   4890 ) -> Result<(), String> {
   4891     for relative in legacy_knowledge_manifest_relatives() {
   4892         let path = workspace_root.join(&relative);
   4893         if path.exists() {
   4894             return Err(format!(
   4895                 "stale knowledge manifest artifact remains at {}",
   4896                 relative
   4897             ));
   4898         }
   4899     }
   4900 
   4901     let value = serde_json::from_str::<Value>(actual_json)
   4902         .map_err(|error| format!("parse knowledge manifest JSON: {error}"))?;
   4903     if value.get("schema_version").and_then(Value::as_u64) != Some(2) {
   4904         return Err("knowledge manifest schema_version must be 2".to_string());
   4905     }
   4906     let contracts = value
   4907         .get("contracts")
   4908         .and_then(Value::as_array)
   4909         .ok_or_else(|| "knowledge manifest contracts must be an array".to_string())?;
   4910     let mut previous_id: Option<String> = None;
   4911     let mut ids = BTreeSet::new();
   4912 
   4913     for contract in contracts {
   4914         let contract_id = contract
   4915             .get("contract_id")
   4916             .and_then(Value::as_str)
   4917             .ok_or_else(|| "knowledge manifest entry missing contract_id".to_string())?;
   4918         if let Some(previous) = previous_id.as_deref()
   4919             && previous > contract_id
   4920         {
   4921             return Err("knowledge manifest contracts must be sorted by contract_id".to_string());
   4922         }
   4923         previous_id = Some(contract_id.to_string());
   4924         if !ids.insert(contract_id.to_string()) {
   4925             return Err(format!(
   4926                 "knowledge manifest has duplicate contract id {contract_id}"
   4927             ));
   4928         }
   4929 
   4930         if contract.get("stability").and_then(Value::as_str) != Some("experimental") {
   4931             return Err(format!(
   4932                 "knowledge manifest contract {contract_id} must be experimental"
   4933             ));
   4934         }
   4935         if contract_id == "radroots.wiki.merge_request.v1"
   4936             && contract.get("content_schema").and_then(Value::as_str) != Some("plain_text")
   4937         {
   4938             return Err(
   4939                 "wiki merge request manifest content_schema must be plain_text".to_string(),
   4940             );
   4941         }
   4942 
   4943         let sdk_builder_support = manifest_bool_field(contract, "sdk_builder_support")?;
   4944         let sdk_draft_support = manifest_bool_field(contract, "sdk_draft_support")?;
   4945         let wasm_tag_builder_support = manifest_bool_field(contract, "wasm_tag_builder_support")?;
   4946         let wasm_verified_decode_support =
   4947             manifest_bool_field(contract, "wasm_verified_decode_support")?;
   4948 
   4949         if KNOWLEDGE_MVP_SUPPORT_CONTRACT_IDS.contains(&contract_id)
   4950             && (!sdk_builder_support || !sdk_draft_support || !wasm_tag_builder_support)
   4951         {
   4952             return Err(format!(
   4953                 "knowledge manifest MVP contract {contract_id} must report SDK and WASM tag support"
   4954             ));
   4955         }
   4956         if KNOWLEDGE_BETA_CONTRACT_IDS.contains(&contract_id)
   4957             && (sdk_builder_support || sdk_draft_support || wasm_tag_builder_support)
   4958         {
   4959             return Err(format!(
   4960                 "knowledge manifest beta contract {contract_id} must not overclaim builder support"
   4961             ));
   4962         }
   4963         if !wasm_verified_decode_support {
   4964             return Err(format!(
   4965                 "knowledge manifest contract {contract_id} must report WASM verified decode support"
   4966             ));
   4967         }
   4968     }
   4969 
   4970     for contract_id in KNOWLEDGE_MVP_SUPPORT_CONTRACT_IDS
   4971         .iter()
   4972         .chain(KNOWLEDGE_BETA_CONTRACT_IDS.iter())
   4973     {
   4974         if !ids.contains(*contract_id) {
   4975             return Err(format!(
   4976                 "knowledge manifest missing required contract {contract_id}"
   4977             ));
   4978         }
   4979     }
   4980 
   4981     Ok(())
   4982 }
   4983 
   4984 fn legacy_knowledge_manifest_relatives() -> [String; 2] {
   4985     [
   4986         KNOWLEDGE_MANIFEST_RELATIVE.replace(".v2.", ".v1."),
   4987         KNOWLEDGE_MANIFEST_SHA256_RELATIVE.replace(".v2.", ".v1."),
   4988     ]
   4989 }
   4990 
   4991 fn manifest_bool_field(contract: &Value, field: &str) -> Result<bool, String> {
   4992     contract
   4993         .get(field)
   4994         .and_then(Value::as_bool)
   4995         .ok_or_else(|| format!("knowledge manifest entry missing boolean field {field}"))
   4996 }
   4997 
   4998 #[cfg(not(test))]
   4999 fn validate_missing_conformance_vectors(
   5000     _workspace_root: &Path,
   5001     vectors_dir: &Path,
   5002 ) -> Result<(), String> {
   5003     Err(format!(
   5004         "conformance vectors directory {} must exist",
   5005         vectors_dir.display()
   5006     ))
   5007 }
   5008 
   5009 #[cfg(test)]
   5010 #[cfg_attr(coverage_nightly, coverage(off))]
   5011 fn validate_missing_conformance_vectors(
   5012     _workspace_root: &Path,
   5013     _vectors_dir: &Path,
   5014 ) -> Result<(), String> {
   5015     Ok(())
   5016 }
   5017 
   5018 #[derive(Debug)]
   5019 struct WorkspacePackageRecord {
   5020     name: String,
   5021     #[cfg_attr(not(test), allow(dead_code))]
   5022     manifest_path: PathBuf,
   5023     publish_enabled: bool,
   5024     publish: Option<PackagePublish>,
   5025     manifest_value: toml::Value,
   5026 }
   5027 
   5028 fn workspace_package_records(workspace_root: &Path) -> Result<Vec<WorkspacePackageRecord>, String> {
   5029     let workspace_manifest =
   5030         parse_toml::<WorkspaceCargoManifest>(&workspace_root.join("Cargo.toml"))?;
   5031     let mut records = Vec::with_capacity(workspace_manifest.workspace.members.len());
   5032     for member in workspace_manifest.workspace.members {
   5033         let manifest_path = workspace_root.join(&member).join("Cargo.toml");
   5034         let raw = match fs::read_to_string(&manifest_path) {
   5035             Ok(raw) => raw,
   5036             Err(e) => return Err(format!("read {}: {e}", manifest_path.display())),
   5037         };
   5038         let manifest_value = match toml::from_str::<toml::Value>(&raw) {
   5039             Ok(value) => value,
   5040             Err(e) => return Err(format!("parse {}: {e}", manifest_path.display())),
   5041         };
   5042         let package_manifest = match toml::from_str::<PackageCargoManifest>(&raw) {
   5043             Ok(manifest) => manifest,
   5044             Err(e) => return Err(format!("parse {}: {e}", manifest_path.display())),
   5045         };
   5046         let name = package_manifest.package.name;
   5047         let publish_enabled = package_publish_enabled(package_manifest.package.publish.as_ref());
   5048         let publish = package_manifest.package.publish.clone();
   5049         records.push(WorkspacePackageRecord {
   5050             name,
   5051             manifest_path,
   5052             publish_enabled,
   5053             publish,
   5054             manifest_value,
   5055         });
   5056     }
   5057     Ok(records)
   5058 }
   5059 
   5060 fn workspace_package_names(workspace_root: &Path) -> Result<Vec<String>, String> {
   5061     Ok(workspace_package_records(workspace_root)?
   5062         .into_iter()
   5063         .map(|record| record.name)
   5064         .collect())
   5065 }
   5066 
   5067 fn coverage_required_workspace_crates(workspace_root: &Path) -> Result<BTreeSet<String>, String> {
   5068     let names = workspace_package_names(workspace_root)?
   5069         .into_iter()
   5070         .filter(|crate_name| !coverage_policy_excludes_workspace_crate(crate_name))
   5071         .collect::<Vec<_>>();
   5072     collect_unique_set(&names, "workspace coverage crates")
   5073 }
   5074 
   5075 fn coverage_policy_excludes_workspace_crate(crate_name: &str) -> bool {
   5076     crate_name.contains("_simplex_") || crate_name.starts_with("simplex_")
   5077 }
   5078 
   5079 #[cfg_attr(not(test), allow(dead_code))]
   5080 fn workspace_package_manifests(workspace_root: &Path) -> Result<BTreeMap<String, PathBuf>, String> {
   5081     let mut manifests = BTreeMap::new();
   5082     for record in workspace_package_records(workspace_root)? {
   5083         if manifests
   5084             .insert(record.name, record.manifest_path)
   5085             .is_some()
   5086         {
   5087             return Err("duplicate workspace package name in manifest map".to_string());
   5088         }
   5089     }
   5090     Ok(manifests)
   5091 }
   5092 
   5093 fn load_coverage_policy(
   5094     contract_root: &Path,
   5095 ) -> Result<crate::coverage::CoveragePolicyFile, String> {
   5096     read_coverage_policy(&coverage_root(contract_root).join("coverage.toml"))
   5097 }
   5098 
   5099 fn coverage_root(contract_root: &Path) -> PathBuf {
   5100     contract_root.to_path_buf()
   5101 }
   5102 
   5103 fn release_contract_path(workspace_root: &Path, _contract_version: &str) -> PathBuf {
   5104     workspace_root.join(RELEASE_POLICY_RELATIVE)
   5105 }
   5106 
   5107 #[cfg(test)]
   5108 fn root_release_policy_path(workspace_root: &Path) -> PathBuf {
   5109     release_contract_path(workspace_root, "1.0.0")
   5110 }
   5111 
   5112 fn resolve_release_contract_path_with_override(
   5113     workspace_root: &Path,
   5114     contract_version: &str,
   5115     release_policy_override: Option<PathBuf>,
   5116 ) -> Result<PathBuf, String> {
   5117     if let Some(path) = release_policy_override {
   5118         if !path.is_file() {
   5119             return Err(format!(
   5120                 "release policy override points to a missing file: {}",
   5121                 path.display()
   5122             ));
   5123         }
   5124         return Ok(path);
   5125     }
   5126 
   5127     let path = release_contract_path(workspace_root, contract_version);
   5128     if !path.is_file() {
   5129         return Err(format!(
   5130             "release publish policy not found; expected {}",
   5131             path.display()
   5132         ));
   5133     }
   5134 
   5135     Ok(path)
   5136 }
   5137 
   5138 #[cfg(test)]
   5139 fn load_release_contract(
   5140     workspace_root: &Path,
   5141     contract_version: &str,
   5142 ) -> Result<ReleaseContractFile, String> {
   5143     load_release_contract_with_override(workspace_root, contract_version, None)
   5144 }
   5145 
   5146 fn load_release_contract_with_override(
   5147     workspace_root: &Path,
   5148     contract_version: &str,
   5149     release_policy_override: Option<PathBuf>,
   5150 ) -> Result<ReleaseContractFile, String> {
   5151     let path = resolve_release_contract_path_with_override(
   5152         workspace_root,
   5153         contract_version,
   5154         release_policy_override,
   5155     )?;
   5156     parse_toml::<ReleaseContractFile>(&path)
   5157 }
   5158 
   5159 #[cfg(test)]
   5160 #[cfg_attr(coverage_nightly, coverage(off))]
   5161 fn should_synthesize_owner_contracts_for_tests(workspace_root: &Path) -> bool {
   5162     workspace_root
   5163         .join("crates")
   5164         .join("core")
   5165         .join("Cargo.toml")
   5166         .is_file()
   5167         && workspace_root
   5168             .join("crates")
   5169             .join("event_codec")
   5170             .join("Cargo.toml")
   5171             .is_file()
   5172         && workspace_root
   5173             .join("crates")
   5174             .join("trade")
   5175             .join("Cargo.toml")
   5176             .is_file()
   5177         && workspace_root
   5178             .join("contracts")
   5179             .join("manifest.toml")
   5180             .is_file()
   5181         && workspace_root
   5182             .join("contracts")
   5183             .join("coverage.toml")
   5184             .is_file()
   5185 }
   5186 
   5187 fn package_publish_enabled(publish: Option<&PackagePublish>) -> bool {
   5188     match publish {
   5189         None => true,
   5190         Some(PackagePublish::Bool(flag)) => *flag,
   5191         Some(PackagePublish::Registries(registries)) => !registries.is_empty(),
   5192     }
   5193 }
   5194 
   5195 #[cfg_attr(not(test), allow(dead_code))]
   5196 fn workspace_package_publish_flags(
   5197     workspace_root: &Path,
   5198 ) -> Result<BTreeMap<String, bool>, String> {
   5199     let mut flags = BTreeMap::new();
   5200     for record in workspace_package_records(workspace_root)? {
   5201         if flags
   5202             .insert(record.name.clone(), record.publish_enabled)
   5203             .is_some()
   5204         {
   5205             return Err(format!("duplicate workspace package name {}", record.name));
   5206         }
   5207     }
   5208     Ok(flags)
   5209 }
   5210 
   5211 fn workspace_package_publish_configs(
   5212     workspace_root: &Path,
   5213 ) -> Result<BTreeMap<String, Option<PackagePublish>>, String> {
   5214     let mut configs = BTreeMap::new();
   5215     for record in workspace_package_records(workspace_root)? {
   5216         if configs
   5217             .insert(record.name.clone(), record.publish.clone())
   5218             .is_some()
   5219         {
   5220             return Err(format!("duplicate workspace package name {}", record.name));
   5221         }
   5222     }
   5223     Ok(configs)
   5224 }
   5225 
   5226 fn read_workspace_package_dependencies(
   5227     workspace_root: &Path,
   5228 ) -> Result<BTreeMap<String, BTreeSet<String>>, String> {
   5229     let package_records = workspace_package_records(workspace_root)?;
   5230     let workspace_names = package_records
   5231         .iter()
   5232         .map(|record| record.name.clone())
   5233         .collect::<BTreeSet<_>>();
   5234 
   5235     let mut deps = BTreeMap::new();
   5236     for record in package_records {
   5237         let mut package_deps = BTreeSet::new();
   5238         for section in ["dependencies", "build-dependencies"] {
   5239             let Some(table) = record
   5240                 .manifest_value
   5241                 .get(section)
   5242                 .and_then(toml::Value::as_table)
   5243             else {
   5244                 continue;
   5245             };
   5246             for dep_name in table.keys() {
   5247                 if workspace_names.contains(dep_name) {
   5248                     package_deps.insert(dep_name.clone());
   5249                 }
   5250             }
   5251         }
   5252         deps.insert(record.name, package_deps);
   5253     }
   5254 
   5255     Ok(deps)
   5256 }
   5257 
   5258 fn validate_publishable_dto_tooling_sources(
   5259     workspace_root: &Path,
   5260     public_crates: &BTreeSet<String>,
   5261 ) -> Result<(), String> {
   5262     let workspace_manifest_value = parse_toml::<toml::Value>(&workspace_root.join("Cargo.toml"))?;
   5263     let package_records = workspace_package_records(workspace_root)?;
   5264 
   5265     for record in package_records {
   5266         if !public_crates.contains(&record.name) {
   5267             continue;
   5268         }
   5269         for section in ["dependencies", "build-dependencies"] {
   5270             let Some(dependencies) = record
   5271                 .manifest_value
   5272                 .get(section)
   5273                 .and_then(toml::Value::as_table)
   5274             else {
   5275                 continue;
   5276             };
   5277             for dependency_name in DTO_TOOLING_DEPENDENCIES {
   5278                 let Some(dependency_value) = dependencies.get(dependency_name) else {
   5279                     continue;
   5280                 };
   5281                 validate_publishable_dto_dependency_source(
   5282                     workspace_manifest_value.as_table(),
   5283                     record.name.as_str(),
   5284                     section,
   5285                     dependency_name,
   5286                     dependency_value,
   5287                 )?;
   5288             }
   5289         }
   5290     }
   5291 
   5292     Ok(())
   5293 }
   5294 
   5295 fn validate_publishable_dto_dependency_source(
   5296     workspace_manifest: Option<&toml::value::Table>,
   5297     crate_name: &str,
   5298     section: &str,
   5299     dependency_name: &str,
   5300     dependency_value: &toml::Value,
   5301 ) -> Result<(), String> {
   5302     let resolved =
   5303         resolve_workspace_dependency_source(workspace_manifest, dependency_name, dependency_value)
   5304             .unwrap_or(dependency_value);
   5305     if dependency_has_source_key(resolved, "git") {
   5306         return Err(format!(
   5307             "public crate {crate_name} {section}.{dependency_name} must use a crates.io DTO tooling dependency, not a git source"
   5308         ));
   5309     }
   5310     if dependency_has_source_key(resolved, "path") {
   5311         return Err(format!(
   5312             "public crate {crate_name} {section}.{dependency_name} must use a crates.io DTO tooling dependency, not a path source"
   5313         ));
   5314     }
   5315     Ok(())
   5316 }
   5317 
   5318 fn resolve_workspace_dependency_source<'a>(
   5319     workspace_manifest: Option<&'a toml::value::Table>,
   5320     dependency_name: &str,
   5321     dependency_value: &toml::Value,
   5322 ) -> Option<&'a toml::Value> {
   5323     if !dependency_has_workspace_true(dependency_value) {
   5324         return None;
   5325     }
   5326     workspace_manifest?
   5327         .get("workspace")?
   5328         .as_table()?
   5329         .get("dependencies")?
   5330         .as_table()?
   5331         .get(dependency_name)
   5332 }
   5333 
   5334 fn dependency_has_workspace_true(value: &toml::Value) -> bool {
   5335     value
   5336         .as_table()
   5337         .and_then(|table| table.get("workspace"))
   5338         .and_then(toml::Value::as_bool)
   5339         .unwrap_or(false)
   5340 }
   5341 
   5342 fn dependency_has_source_key(value: &toml::Value, key: &str) -> bool {
   5343     value.as_table().and_then(|table| table.get(key)).is_some()
   5344 }
   5345 
   5346 fn join_set(items: &BTreeSet<String>) -> String {
   5347     items.iter().cloned().collect::<Vec<_>>().join(", ")
   5348 }
   5349 
   5350 fn collect_unique_set(items: &[String], field: &str) -> Result<BTreeSet<String>, String> {
   5351     let mut set = BTreeSet::new();
   5352     for item in items {
   5353         if item.trim().is_empty() {
   5354             return Err(format!("{field} contains an empty crate name"));
   5355         }
   5356         if !set.insert(item.clone()) {
   5357             return Err(format!("{field} has duplicate crate {}", item));
   5358         }
   5359     }
   5360     Ok(set)
   5361 }
   5362 
   5363 fn collect_non_empty_set(items: &[String], field: &str) -> Result<BTreeSet<String>, String> {
   5364     let mut set = BTreeSet::new();
   5365     for item in items {
   5366         if item.trim().is_empty() {
   5367             return Err(format!("{field} contains an empty value"));
   5368         }
   5369         if !set.insert(item.clone()) {
   5370             return Err(format!("{field} has duplicate value {}", item));
   5371         }
   5372     }
   5373     Ok(set)
   5374 }
   5375 
   5376 fn validate_crate_identifier(value: &str, field: &str) -> Result<(), String> {
   5377     let trimmed = value.trim();
   5378     if trimmed.is_empty() {
   5379         return Err(format!("{field} is required"));
   5380     }
   5381     if trimmed != value
   5382         || trimmed.contains('/')
   5383         || trimmed.contains('\\')
   5384         || trimmed.contains("..")
   5385         || trimmed == "radroots_sdk"
   5386     {
   5387         return Err(format!("{field} must be a crate identifier"));
   5388     }
   5389     Ok(())
   5390 }
   5391 
   5392 fn validate_surface_metadata(surface: &Surface) -> Result<(), String> {
   5393     if let Some(tiers) = &surface.rust_crate_tiers {
   5394         let mut tier_crates = BTreeSet::new();
   5395         for (field, crates) in [
   5396             (
   5397                 "surface.rust_crate_tiers.advanced_substrate",
   5398                 &tiers.advanced_substrate,
   5399             ),
   5400             (
   5401                 "surface.rust_crate_tiers.published_support",
   5402                 &tiers.published_support,
   5403             ),
   5404             (
   5405                 "surface.rust_crate_tiers.deferred_publication",
   5406                 &tiers.deferred_publication,
   5407             ),
   5408         ] {
   5409             let entries = collect_unique_set(crates, field)?;
   5410             if entries.is_empty() {
   5411                 return Err(format!("{field} must not be empty"));
   5412             }
   5413             for crate_name in entries {
   5414                 if !tier_crates.insert(crate_name.clone()) {
   5415                     return Err(format!(
   5416                         "surface.rust_crate_tiers has duplicate crate {crate_name}"
   5417                     ));
   5418                 }
   5419             }
   5420         }
   5421     }
   5422 
   5423     if let Some(replica) = &surface.internal_replica_crates {
   5424         validate_crate_identifier(&replica.schema, "surface.internal_replica_crates.schema")?;
   5425         validate_crate_identifier(&replica.storage, "surface.internal_replica_crates.storage")?;
   5426         validate_crate_identifier(&replica.sync, "surface.internal_replica_crates.sync")?;
   5427     }
   5428 
   5429     Ok(())
   5430 }
   5431 
   5432 fn validate_policy_metadata(policy: &Policy) -> Result<(), String> {
   5433     if !policy.exclude_internal_workspace_crates
   5434         || !policy.require_reproducible_exports
   5435         || !policy.require_conformance_vectors
   5436     {
   5437         return Err("contract policy flags must all be true".to_string());
   5438     }
   5439     if let Some(replica) = &policy.replica
   5440         && (!replica.forbid_legacy_alias_identifiers
   5441             || !replica.require_transport_agnostic_sync_contract
   5442             || !replica.require_deterministic_emit_ingest)
   5443     {
   5444         return Err("contract replica policy flags must all be true".to_string());
   5445     }
   5446     Ok(())
   5447 }
   5448 
   5449 fn parse_replica_transfer_constant(path: &Path, name: &str) -> Result<u32, String> {
   5450     let source =
   5451         fs::read_to_string(path).map_err(|error| format!("read {}: {error}", path.display()))?;
   5452     let declaration_prefix = format!("pub const {name}: u32 =");
   5453     let mut value = None;
   5454     for line in source.lines() {
   5455         let Some(raw_value) = line.trim().strip_prefix(&declaration_prefix) else {
   5456             continue;
   5457         };
   5458         let raw_value = raw_value.trim().strip_suffix(';').ok_or_else(|| {
   5459             format!(
   5460                 "replica transfer constant {name} in {} must terminate with a semicolon",
   5461                 path.display()
   5462             )
   5463         })?;
   5464         let parsed = raw_value.parse::<u32>().map_err(|error| {
   5465             format!(
   5466                 "replica transfer constant {name} in {} must be a u32 literal: {error}",
   5467                 path.display()
   5468             )
   5469         })?;
   5470         if value.replace(parsed).is_some() {
   5471             return Err(format!(
   5472                 "replica transfer constant {name} must be declared exactly once in {}",
   5473                 path.display()
   5474             ));
   5475         }
   5476     }
   5477     value.ok_or_else(|| {
   5478         format!(
   5479             "replica transfer constant {name} is missing from {}",
   5480             path.display()
   5481         )
   5482     })
   5483 }
   5484 
   5485 fn has_exact_legacy_ingest_cfg(attributes: &[syn::Attribute]) -> bool {
   5486     let mut cfg_attributes = attributes
   5487         .iter()
   5488         .filter(|attribute| attribute.path().is_ident("cfg"));
   5489     let Some(attribute) = cfg_attributes.next() else {
   5490         return false;
   5491     };
   5492     if cfg_attributes.next().is_some() {
   5493         return false;
   5494     }
   5495     let syn::Meta::List(arguments) = &attribute.meta else {
   5496         return false;
   5497     };
   5498     let Ok(predicate) = arguments.parse_args::<syn::Meta>() else {
   5499         return false;
   5500     };
   5501     let syn::Meta::NameValue(feature) = predicate else {
   5502         return false;
   5503     };
   5504     if !feature.path.is_ident("feature") {
   5505         return false;
   5506     }
   5507     matches!(
   5508         feature.value,
   5509         syn::Expr::Lit(syn::ExprLit {
   5510             lit: syn::Lit::Str(value),
   5511             ..
   5512         }) if value.value() == "legacy-ingest"
   5513     )
   5514 }
   5515 
   5516 fn replica_use_tree_references_ingest(tree: &syn::UseTree) -> bool {
   5517     match tree {
   5518         syn::UseTree::Path(path) => {
   5519             path.ident == "ingest" || replica_use_tree_references_ingest(&path.tree)
   5520         }
   5521         syn::UseTree::Name(name) => name.ident == "ingest",
   5522         syn::UseTree::Rename(rename) => rename.ident == "ingest",
   5523         syn::UseTree::Group(group) => group.items.iter().any(replica_use_tree_references_ingest),
   5524         syn::UseTree::Glob(_) => false,
   5525     }
   5526 }
   5527 
   5528 fn collect_public_replica_ingest_exports<'a>(
   5529     items: &'a [syn::Item],
   5530     exports: &mut Vec<&'a syn::ItemUse>,
   5531 ) {
   5532     for item in items {
   5533         match item {
   5534             syn::Item::Use(export)
   5535                 if matches!(&export.vis, syn::Visibility::Public(_))
   5536                     && replica_use_tree_references_ingest(&export.tree) =>
   5537             {
   5538                 exports.push(export);
   5539             }
   5540             syn::Item::Mod(module) if matches!(&module.vis, syn::Visibility::Public(_)) => {
   5541                 if let Some((_, nested_items)) = &module.content {
   5542                     collect_public_replica_ingest_exports(nested_items, exports);
   5543                 }
   5544             }
   5545             _ => {}
   5546         }
   5547     }
   5548 }
   5549 
   5550 fn validate_replica_legacy_ingest_exports(lib_path: &Path, source: &str) -> Result<(), String> {
   5551     let syntax = syn::parse_file(source)
   5552         .map_err(|error| format!("parse replica sync source {}: {error}", lib_path.display()))?;
   5553     let ingest_modules = syntax
   5554         .items
   5555         .iter()
   5556         .filter_map(|item| match item {
   5557             syn::Item::Mod(module) if module.ident == "ingest" => Some(module),
   5558             _ => None,
   5559         })
   5560         .collect::<Vec<_>>();
   5561     if ingest_modules.len() != 1 {
   5562         return Err(format!(
   5563             "replica legacy ingest source {} must declare exactly one ingest module",
   5564             lib_path.display()
   5565         ));
   5566     }
   5567     let ingest_module = ingest_modules[0];
   5568     if !matches!(&ingest_module.vis, syn::Visibility::Public(_)) {
   5569         return Err(format!(
   5570             "replica legacy ingest module in {} must remain public",
   5571             lib_path.display()
   5572         ));
   5573     }
   5574     if !has_exact_legacy_ingest_cfg(&ingest_module.attrs) {
   5575         return Err(format!(
   5576             "replica legacy ingest module in {} must be guarded by exact #[cfg(feature = \"legacy-ingest\")]",
   5577             lib_path.display()
   5578         ));
   5579     }
   5580 
   5581     let mut ingest_exports = Vec::new();
   5582     collect_public_replica_ingest_exports(&syntax.items, &mut ingest_exports);
   5583     if ingest_exports.is_empty() {
   5584         return Err(format!(
   5585             "replica legacy ingest source {} must publicly re-export the ingest API",
   5586             lib_path.display()
   5587         ));
   5588     }
   5589     if ingest_exports
   5590         .iter()
   5591         .any(|export| !has_exact_legacy_ingest_cfg(&export.attrs))
   5592     {
   5593         return Err(format!(
   5594             "every public replica ingest re-export in {} must be guarded by exact #[cfg(feature = \"legacy-ingest\")]",
   5595             lib_path.display()
   5596         ));
   5597     }
   5598     Ok(())
   5599 }
   5600 
   5601 fn validate_replica_policy_source_witnesses(sync_root: &Path) -> Result<(), String> {
   5602     let cargo_path = sync_root.join("Cargo.toml");
   5603     let cargo_source = fs::read_to_string(&cargo_path)
   5604         .map_err(|error| format!("read {}: {error}", cargo_path.display()))?;
   5605     let cargo: toml::Value = toml::from_str(&cargo_source)
   5606         .map_err(|error| format!("parse {}: {error}", cargo_path.display()))?;
   5607     let features = cargo
   5608         .get("features")
   5609         .and_then(toml::Value::as_table)
   5610         .ok_or_else(|| format!("replica sync {} must define features", cargo_path.display()))?;
   5611     let default_features = features
   5612         .get("default")
   5613         .and_then(toml::Value::as_array)
   5614         .ok_or_else(|| {
   5615             format!(
   5616                 "replica sync {} must define default features",
   5617                 cargo_path.display()
   5618             )
   5619         })?;
   5620     let mut pending_default_features = default_features
   5621         .iter()
   5622         .filter_map(toml::Value::as_str)
   5623         .collect::<Vec<_>>();
   5624     let mut visited_default_features = BTreeSet::new();
   5625     while let Some(feature) = pending_default_features.pop() {
   5626         if !visited_default_features.insert(feature) {
   5627             continue;
   5628         }
   5629         if feature == "legacy-ingest" {
   5630             return Err(format!(
   5631                 "replica legacy-ingest must not be enabled by default features in {}",
   5632                 cargo_path.display()
   5633             ));
   5634         }
   5635         if let Some(members) = features.get(feature).and_then(toml::Value::as_array) {
   5636             pending_default_features.extend(
   5637                 members
   5638                     .iter()
   5639                     .filter_map(toml::Value::as_str)
   5640                     .filter(|member| features.contains_key(*member)),
   5641             );
   5642         }
   5643     }
   5644     let legacy_features = features
   5645         .get("legacy-ingest")
   5646         .and_then(toml::Value::as_array)
   5647         .ok_or_else(|| {
   5648             format!(
   5649                 "replica sync {} must define the explicit legacy-ingest feature",
   5650                 cargo_path.display()
   5651             )
   5652         })?;
   5653     if !legacy_features
   5654         .iter()
   5655         .filter_map(toml::Value::as_str)
   5656         .any(|feature| feature == "std")
   5657     {
   5658         return Err(format!(
   5659             "replica legacy-ingest feature in {} must enable std",
   5660             cargo_path.display()
   5661         ));
   5662     }
   5663 
   5664     let lib_path = sync_root.join("src/lib.rs");
   5665     let lib_source = fs::read_to_string(&lib_path)
   5666         .map_err(|error| format!("read {}: {error}", lib_path.display()))?;
   5667     validate_replica_legacy_ingest_exports(&lib_path, &lib_source)?;
   5668 
   5669     let types_path = sync_root.join("src/types.rs");
   5670     let types_source = fs::read_to_string(&types_path)
   5671         .map_err(|error| format!("read {}: {error}", types_path.display()))?;
   5672     for type_name in [
   5673         "RadrootsReplicaFarmSelector",
   5674         "RadrootsReplicaSyncOptions",
   5675         "RadrootsReplicaSyncRequest",
   5676     ] {
   5677         let witness = format!("#[serde(deny_unknown_fields)]\npub struct {type_name}");
   5678         if !types_source.contains(&witness) {
   5679             return Err(format!(
   5680                 "replica request type {type_name} must place #[serde(deny_unknown_fields)] immediately before its public struct declaration in {}",
   5681                 types_path.display()
   5682             ));
   5683         }
   5684     }
   5685     if types_source.contains("include_profiles") {
   5686         return Err(format!(
   5687             "retired replica request identifier include_profiles is forbidden in {}",
   5688             types_path.display()
   5689         ));
   5690     }
   5691 
   5692     let emit_path = sync_root.join("src/emit.rs");
   5693     let emit_source = fs::read_to_string(&emit_path)
   5694         .map_err(|error| format!("read {}: {error}", emit_path.display()))?;
   5695     let test_module_marker = "#[cfg(test)]\nmod tests {";
   5696     let test_module_start = emit_source.rfind(test_module_marker).ok_or_else(|| {
   5697         format!(
   5698             "replica emit source {} must keep its bottom test module behind #[cfg(test)]",
   5699             emit_path.display()
   5700         )
   5701     })?;
   5702     let production_source = &emit_source[..test_module_start];
   5703     if !production_source.contains("pub fn radroots_replica_sync_all_with_options(") {
   5704         return Err(format!(
   5705             "replica emit source {} is missing radroots_replica_sync_all_with_options",
   5706             emit_path.display()
   5707         ));
   5708     }
   5709     let production_code = production_source
   5710         .lines()
   5711         .filter(|line| !line.trim_start().starts_with("//"))
   5712         .collect::<Vec<_>>()
   5713         .join("\n");
   5714     for identifier in production_code
   5715         .split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
   5716         .filter(|identifier| !identifier.is_empty())
   5717     {
   5718         if identifier.to_ascii_lowercase().contains("profile") {
   5719             return Err(format!(
   5720                 "replica emit production source {} must not contain Profile-related identifier {identifier}",
   5721                 emit_path.display()
   5722             ));
   5723         }
   5724     }
   5725     let compact_production = production_code
   5726         .chars()
   5727         .filter(|character| !character.is_ascii_whitespace())
   5728         .collect::<String>();
   5729     if compact_production.contains("kind:0") {
   5730         return Err(format!(
   5731             "replica emit production source {} must not construct a literal kind-0 event",
   5732             emit_path.display()
   5733         ));
   5734     }
   5735 
   5736     Ok(())
   5737 }
   5738 
   5739 fn validate_replica_contract(bundle: &ContractBundle, workspace_root: &Path) -> Result<(), String> {
   5740     let replica = &bundle.replica;
   5741     if replica.schema_version != 1 {
   5742         return Err("replica contract schema_version must be 1".to_string());
   5743     }
   5744     if replica.contract.name != REPLICA_CONTRACT_NAME {
   5745         return Err(format!(
   5746             "replica contract name must be {REPLICA_CONTRACT_NAME}"
   5747         ));
   5748     }
   5749     if replica.contract.version != bundle.manifest.contract.version {
   5750         return Err(format!(
   5751             "replica contract version {} must match manifest contract version {}",
   5752             replica.contract.version, bundle.manifest.contract.version
   5753         ));
   5754     }
   5755     if replica.contract.purpose.trim().is_empty() {
   5756         return Err("replica contract purpose is required".to_string());
   5757     }
   5758 
   5759     let manifest_family = bundle
   5760         .manifest
   5761         .surface
   5762         .internal_replica_crates
   5763         .as_ref()
   5764         .ok_or_else(|| "surface.internal_replica_crates is required".to_string())?;
   5765     for (field, actual, expected) in [
   5766         (
   5767             "schema",
   5768             replica.crate_family.schema.as_str(),
   5769             manifest_family.schema.as_str(),
   5770         ),
   5771         (
   5772             "storage",
   5773             replica.crate_family.storage.as_str(),
   5774             manifest_family.storage.as_str(),
   5775         ),
   5776         (
   5777             "sync",
   5778             replica.crate_family.sync.as_str(),
   5779             manifest_family.sync.as_str(),
   5780         ),
   5781     ] {
   5782         validate_crate_identifier(actual, &format!("replica.crate_family.{field}"))?;
   5783         if actual != expected {
   5784             return Err(format!(
   5785                 "replica crate_family.{field} {actual} must match surface.internal_replica_crates.{field} {expected}"
   5786             ));
   5787         }
   5788     }
   5789 
   5790     let package_manifests = workspace_package_manifests(workspace_root)?;
   5791     for (field, crate_name) in [
   5792         ("schema", replica.crate_family.schema.as_str()),
   5793         ("storage", replica.crate_family.storage.as_str()),
   5794         ("sync", replica.crate_family.sync.as_str()),
   5795     ] {
   5796         if !package_manifests.contains_key(crate_name) {
   5797             return Err(format!(
   5798                 "replica crate_family.{field} {crate_name} must name a workspace package"
   5799             ));
   5800         }
   5801     }
   5802 
   5803     let manifest_policy = bundle
   5804         .manifest
   5805         .policy
   5806         .replica
   5807         .as_ref()
   5808         .ok_or_else(|| "policy.replica is required".to_string())?;
   5809     let policy_parity = [
   5810         (
   5811             "transport_agnostic_sync_core",
   5812             replica.policy.transport_agnostic_sync_core,
   5813             manifest_policy.require_transport_agnostic_sync_contract,
   5814         ),
   5815         (
   5816             "deterministic_emit_and_ingest",
   5817             replica.policy.deterministic_emit_and_ingest,
   5818             manifest_policy.require_deterministic_emit_ingest,
   5819         ),
   5820         (
   5821             "forbid_legacy_alias_identifiers",
   5822             replica.policy.forbid_legacy_alias_identifiers,
   5823             manifest_policy.forbid_legacy_alias_identifiers,
   5824         ),
   5825     ];
   5826     for (field, actual, expected) in policy_parity {
   5827         if !actual || actual != expected {
   5828             return Err(format!(
   5829                 "replica policy.{field} must be true and match manifest policy.replica"
   5830             ));
   5831         }
   5832     }
   5833     if replica.policy.profile_event_emission != "excluded" {
   5834         return Err("replica policy.profile_event_emission must be excluded".to_string());
   5835     }
   5836     if replica.policy.unknown_sync_request_fields != "reject" {
   5837         return Err("replica policy.unknown_sync_request_fields must be reject".to_string());
   5838     }
   5839     for (field, actual, expected) in [
   5840         (
   5841             "classified_listing_signature_verification",
   5842             replica
   5843                 .policy
   5844                 .classified_listing_signature_verification
   5845                 .as_str(),
   5846             "required_before_state",
   5847         ),
   5848         (
   5849             "classified_listing_head_selection",
   5850             replica.policy.classified_listing_head_selection.as_str(),
   5851             "raw_before_profile",
   5852         ),
   5853         (
   5854             "classified_listing_operational_projection",
   5855             replica
   5856                 .policy
   5857                 .classified_listing_operational_projection
   5858                 .as_str(),
   5859             "operational_partition_only",
   5860         ),
   5861         (
   5862             "classified_listing_excluded_or_rejected_head",
   5863             replica
   5864                 .policy
   5865                 .classified_listing_excluded_or_rejected_head
   5866                 .as_str(),
   5867             "remove_projection_and_advance",
   5868         ),
   5869         (
   5870             "classified_listing_head_only_ingest",
   5871             replica.policy.classified_listing_head_only_ingest.as_str(),
   5872             "reject_require_profile_aware",
   5873         ),
   5874         (
   5875             "legacy_bare_envelope_ingest",
   5876             replica.policy.legacy_bare_envelope_ingest.as_str(),
   5877             "explicit_non_default_feature_only",
   5878         ),
   5879         (
   5880             "legacy_ingest_feature",
   5881             replica.policy.legacy_ingest_feature.as_str(),
   5882             "legacy-ingest",
   5883         ),
   5884         (
   5885             "phase_1_ingest_replacement",
   5886             replica.policy.phase_1_ingest_replacement.as_str(),
   5887             "none",
   5888         ),
   5889         (
   5890             "future_product_ingest_input",
   5891             replica.policy.future_product_ingest_input.as_str(),
   5892             "store_produced_verified_valid_visible_admission",
   5893         ),
   5894     ] {
   5895         if actual != expected {
   5896             return Err(format!("replica policy.{field} must be {expected}"));
   5897         }
   5898     }
   5899 
   5900     if replica.transfer.version != REPLICA_TRANSFER_VERSION {
   5901         return Err(format!(
   5902             "replica transfer.version must be {REPLICA_TRANSFER_VERSION}"
   5903         ));
   5904     }
   5905     if replica.transfer.constant != REPLICA_TRANSFER_CONSTANT {
   5906         return Err(format!(
   5907             "replica transfer.constant must be {REPLICA_TRANSFER_CONSTANT}"
   5908         ));
   5909     }
   5910     let sync_manifest = package_manifests
   5911         .get(&replica.crate_family.sync)
   5912         .expect("replica sync workspace package was validated");
   5913     let sync_root = sync_manifest
   5914         .parent()
   5915         .expect("workspace package manifest has a parent");
   5916     validate_replica_policy_source_witnesses(sync_root)?;
   5917     let expected_source = sync_root
   5918         .strip_prefix(workspace_root)
   5919         .expect("workspace package lives under the workspace root")
   5920         .join("src/types.rs");
   5921     if Path::new(&replica.transfer.source) != expected_source {
   5922         return Err(format!(
   5923             "replica transfer.source {} must be {}",
   5924             replica.transfer.source,
   5925             expected_source.display()
   5926         ));
   5927     }
   5928     let source_path = workspace_root.join(&replica.transfer.source);
   5929     let source_version = parse_replica_transfer_constant(&source_path, &replica.transfer.constant)?;
   5930     if source_version != replica.transfer.version {
   5931         return Err(format!(
   5932             "replica transfer source constant {} value {} must match contract version {}",
   5933             replica.transfer.constant, source_version, replica.transfer.version
   5934         ));
   5935     }
   5936 
   5937     Ok(())
   5938 }
   5939 
   5940 fn validate_operations_contract(
   5941     bundle: &ContractBundle,
   5942     operations_manifest: &OperationsContractManifest,
   5943     workspace_root: &Path,
   5944 ) -> Result<(), String> {
   5945     validate_conformance_schema(workspace_root)?;
   5946     let conformance_root = conformance_root(workspace_root);
   5947     if operations_manifest.contract.name.trim().is_empty() {
   5948         return Err("operations contract name is required".to_string());
   5949     }
   5950     if operations_manifest.contract.version.trim().is_empty() {
   5951         return Err("operations contract version is required".to_string());
   5952     }
   5953     if operations_manifest.contract.source.trim().is_empty() {
   5954         return Err("operations contract source is required".to_string());
   5955     }
   5956     if operations_manifest.contract.name != bundle.manifest.contract.name {
   5957         return Err("operations contract name must match manifest contract name".to_string());
   5958     }
   5959     if operations_manifest.contract.version != bundle.manifest.contract.version {
   5960         return Err("operations contract version must match manifest contract version".to_string());
   5961     }
   5962     if operations_manifest.contract.source != bundle.manifest.contract.source {
   5963         return Err("operations contract source must match manifest contract source".to_string());
   5964     }
   5965 
   5966     let domains = collect_non_empty_set(&operations_manifest.public.domains, "public.domains")?;
   5967     if domains.is_empty() {
   5968         return Err("public.domains must not be empty".to_string());
   5969     }
   5970     let shared_types = collect_non_empty_set(
   5971         &operations_manifest.shared_types.public,
   5972         "shared_types.public",
   5973     )?;
   5974     if shared_types.is_empty() {
   5975         return Err("shared_types.public must not be empty".to_string());
   5976     }
   5977     validate_no_retired_operation_event_names(
   5978         &operations_manifest.shared_types.public,
   5979         "shared_types.public",
   5980     )?;
   5981     let error_classes =
   5982         collect_non_empty_set(&operations_manifest.errors.classes, "errors.classes")?;
   5983     if error_classes.is_empty() {
   5984         return Err("errors.classes must not be empty".to_string());
   5985     }
   5986     if operations_manifest.operations.is_empty() {
   5987         return Err("operations map must not be empty".to_string());
   5988     }
   5989 
   5990     if let Some(provenance) = &operations_manifest.implementation_provenance {
   5991         let manifest_models = collect_unique_set(
   5992             &bundle.manifest.surface.model_crates,
   5993             "surface.model_crates",
   5994         )?;
   5995         let manifest_algorithms = collect_unique_set(
   5996             &bundle.manifest.surface.algorithm_crates,
   5997             "surface.algorithm_crates",
   5998         )?;
   5999         let provenance_models = collect_unique_set(
   6000             &provenance.model_crates,
   6001             "implementation_provenance.model_crates",
   6002         )?;
   6003         let provenance_algorithms = collect_unique_set(
   6004             &provenance.algorithm_crates,
   6005             "implementation_provenance.algorithm_crates",
   6006         )?;
   6007         if provenance_models != manifest_models || provenance_algorithms != manifest_algorithms {
   6008             return Err(
   6009                 "operations implementation_provenance must match manifest surface crates"
   6010                     .to_string(),
   6011             );
   6012         }
   6013     }
   6014 
   6015     let mut operation_ids = BTreeSet::new();
   6016     for (operation_key, operation) in &operations_manifest.operations {
   6017         if operation_key.trim().is_empty() {
   6018             return Err("operations map contains an empty key".to_string());
   6019         }
   6020         if operation.domain.trim().is_empty() {
   6021             return Err(format!("operation {} domain is required", operation_key));
   6022         }
   6023         if !domains.contains(&operation.domain) {
   6024             return Err(format!(
   6025                 "operation {} references unknown domain {}",
   6026                 operation_key, operation.domain
   6027             ));
   6028         }
   6029         if operation.id.trim().is_empty() {
   6030             return Err(format!("operation {} id is required", operation_key));
   6031         }
   6032         if !operation_ids.insert(operation.id.clone()) {
   6033             return Err(format!("operations has duplicate id {}", operation.id));
   6034         }
   6035         if operation.stability.trim().is_empty() {
   6036             return Err(format!("operation {} stability is required", operation.id));
   6037         }
   6038         if !operation.deterministic {
   6039             return Err(format!(
   6040                 "operation {} deterministic must be true for the public contract",
   6041                 operation.id
   6042             ));
   6043         }
   6044         if operation.inputs.is_empty() {
   6045             return Err(format!(
   6046                 "operation {} inputs must not be empty",
   6047                 operation.id
   6048             ));
   6049         }
   6050         let _ = collect_non_empty_set(
   6051             &operation.inputs,
   6052             &format!("operation {} inputs", operation.id),
   6053         )?;
   6054         validate_no_retired_operation_event_names(
   6055             &operation.inputs,
   6056             &format!("operation {} inputs", operation.id),
   6057         )?;
   6058         if operation.outputs.is_empty() {
   6059             return Err(format!(
   6060                 "operation {} outputs must not be empty",
   6061                 operation.id
   6062             ));
   6063         }
   6064         let _ = collect_non_empty_set(
   6065             &operation.outputs,
   6066             &format!("operation {} outputs", operation.id),
   6067         )?;
   6068         validate_no_retired_operation_event_names(
   6069             &operation.outputs,
   6070             &format!("operation {} outputs", operation.id),
   6071         )?;
   6072         if !error_classes.contains(&operation.error_class) {
   6073             return Err(format!(
   6074                 "operation {} references unknown error class {}",
   6075                 operation.id, operation.error_class
   6076             ));
   6077         }
   6078         if operation.signing.trim().is_empty() {
   6079             return Err(format!("operation {} signing is required", operation.id));
   6080         }
   6081         if operation.transport.trim().is_empty() {
   6082             return Err(format!("operation {} transport is required", operation.id));
   6083         }
   6084         if operation.implementation.rust_modules.is_empty() {
   6085             return Err(format!(
   6086                 "operation {} implementation.rust_modules must not be empty",
   6087                 operation.id
   6088             ));
   6089         }
   6090         let _ = collect_non_empty_set(
   6091             &operation.implementation.rust_types,
   6092             &format!("operation {} implementation.rust_types", operation.id),
   6093         )?;
   6094         validate_no_retired_operation_event_names(
   6095             &operation.implementation.rust_types,
   6096             &format!("operation {} implementation.rust_types", operation.id),
   6097         )?;
   6098         for rust_module in &operation.implementation.rust_modules {
   6099             if rust_module.trim().is_empty() {
   6100                 return Err(format!(
   6101                     "operation {} implementation.rust_modules contains an empty value",
   6102                     operation.id
   6103                 ));
   6104             }
   6105             let path = workspace_root.join(rust_module);
   6106             if !path.is_file() {
   6107                 return Err(format!(
   6108                     "operation {} references missing rust module {}",
   6109                     operation.id, rust_module
   6110                 ));
   6111             }
   6112         }
   6113         if operation.conformance.vector.trim().is_empty() {
   6114             return Err(format!(
   6115                 "operation {} conformance.vector is required",
   6116                 operation.id
   6117             ));
   6118         }
   6119         if !operation
   6120             .conformance
   6121             .vector
   6122             .starts_with("contracts/conformance/")
   6123         {
   6124             return Err(format!(
   6125                 "operation {} conformance.vector must live under contracts/conformance/",
   6126                 operation.id
   6127             ));
   6128         }
   6129         let vector_path = workspace_root.join(&operation.conformance.vector);
   6130         if !vector_path.starts_with(&conformance_root) {
   6131             return Err(format!(
   6132                 "operation {} conformance.vector must resolve under {}",
   6133                 operation.id,
   6134                 conformance_root.display()
   6135             ));
   6136         }
   6137         let vector =
   6138             validate_conformance_vector_file(&vector_path, &operations_manifest.contract.version)?;
   6139         validate_operation_case_kinds(operation, &vector)?;
   6140     }
   6141 
   6142     Ok(())
   6143 }
   6144 
   6145 fn validate_capsule_operation_authority(
   6146     operations_manifest: &OperationsContractManifest,
   6147     workspace_root: &Path,
   6148 ) -> Result<(), String> {
   6149     let shared_types = collect_non_empty_set(
   6150         &operations_manifest.shared_types.public,
   6151         "shared_types.public",
   6152     )?;
   6153     validate_comment_operation_authority(operations_manifest, workspace_root)?;
   6154     validate_deletion_operation_authority(operations_manifest, workspace_root)?;
   6155     validate_admission_operation_authority(operations_manifest, workspace_root)?;
   6156     validate_post_operation_authority(operations_manifest, workspace_root)?;
   6157     validate_calendar_operation_authority(operations_manifest, &shared_types)?;
   6158     validate_food_availability_operation_authority(operations_manifest, workspace_root)
   6159 }
   6160 
   6161 fn validate_operation_case_kinds(
   6162     operation: &PublicOperationContract,
   6163     vector: &ConformanceVectorFile,
   6164 ) -> Result<(), String> {
   6165     if operation.conformance.case_kinds.is_empty() {
   6166         return Ok(());
   6167     }
   6168     let case_kinds = collect_non_empty_set(
   6169         &operation.conformance.case_kinds,
   6170         &format!("operation {} conformance.case_kinds", operation.id),
   6171     )?;
   6172     if case_kinds.len() != operation.conformance.case_kinds.len() {
   6173         return Err(format!(
   6174             "operation {} conformance.case_kinds must not contain duplicates",
   6175             operation.id
   6176         ));
   6177     }
   6178     let prefix = format!("{}.", operation.id);
   6179     let vector_kinds = vector
   6180         .vectors
   6181         .iter()
   6182         .map(|entry| entry.kind.as_str())
   6183         .collect::<BTreeSet<_>>();
   6184     for case_kind in case_kinds {
   6185         if !case_kind.starts_with(&prefix) {
   6186             return Err(format!(
   6187                 "operation {} conformance case kind {} must start with {}",
   6188                 operation.id, case_kind, prefix
   6189             ));
   6190         }
   6191         if !vector_kinds.contains(case_kind.as_str()) {
   6192             return Err(format!(
   6193                 "operation {} conformance case kind {} is absent from {}",
   6194                 operation.id, case_kind, operation.conformance.vector
   6195             ));
   6196         }
   6197     }
   6198     Ok(())
   6199 }
   6200 
   6201 fn validate_post_operation_authority(
   6202     manifest: &OperationsContractManifest,
   6203     workspace_root: &Path,
   6204 ) -> Result<(), String> {
   6205     let vector = validate_conformance_vector_file(
   6206         &workspace_root.join(POST_CONFORMANCE_VECTOR_RELATIVE),
   6207         &manifest.contract.version,
   6208     )?;
   6209     validate_post_operation_inventory(manifest, &vector)
   6210 }
   6211 
   6212 fn validate_post_operation_inventory(
   6213     manifest: &OperationsContractManifest,
   6214     vector: &ConformanceVectorFile,
   6215 ) -> Result<(), String> {
   6216     let shared_types = collect_non_empty_set(
   6217         &manifest.shared_types.public,
   6218         "post operation shared_types.public",
   6219     )?;
   6220     for required in REQUIRED_POST_PUBLIC_TYPES {
   6221         if !shared_types.contains(required) {
   6222             return Err(format!(
   6223                 "post operation authority requires shared public type {required}"
   6224             ));
   6225         }
   6226     }
   6227 
   6228     let expected_keys = POST_OPERATION_EXPECTATIONS
   6229         .iter()
   6230         .map(|expectation| expectation.key.to_string())
   6231         .collect::<BTreeSet<_>>();
   6232     let actual_keys = manifest
   6233         .operations
   6234         .iter()
   6235         .filter(|(key, operation)| {
   6236             operation.conformance.vector == POST_CONFORMANCE_VECTOR_RELATIVE
   6237                 || POST_OPERATION_KEY_PREFIXES
   6238                     .iter()
   6239                     .any(|prefix| key.starts_with(prefix))
   6240                 || POST_OPERATION_ID_PREFIXES
   6241                     .iter()
   6242                     .any(|prefix| operation.id.starts_with(prefix))
   6243         })
   6244         .map(|(key, _)| key.clone())
   6245         .collect::<BTreeSet<_>>();
   6246     if actual_keys != expected_keys {
   6247         let missing = expected_keys
   6248             .difference(&actual_keys)
   6249             .cloned()
   6250             .collect::<BTreeSet<_>>();
   6251         let unexpected = actual_keys
   6252             .difference(&expected_keys)
   6253             .cloned()
   6254             .collect::<BTreeSet<_>>();
   6255         return Err(format!(
   6256             "post operation authority drift: missing {}; unexpected {}",
   6257             join_set(&missing),
   6258             join_set(&unexpected)
   6259         ));
   6260     }
   6261 
   6262     let mut owners = BTreeMap::new();
   6263     for expected in POST_OPERATION_EXPECTATIONS {
   6264         let operation = manifest
   6265             .operations
   6266             .get(expected.key)
   6267             .ok_or_else(|| format!("post operation {} is required", expected.key))?;
   6268         validate_post_operation_scalar(expected.key, "domain", &operation.domain, "social")?;
   6269         validate_post_operation_scalar(expected.key, "id", &operation.id, expected.id)?;
   6270         validate_post_operation_scalar(expected.key, "stability", &operation.stability, "beta")?;
   6271         validate_post_operation_scalar(
   6272             expected.key,
   6273             "error_class",
   6274             &operation.error_class,
   6275             expected.error_class,
   6276         )?;
   6277         validate_post_operation_scalar(
   6278             expected.key,
   6279             "signing",
   6280             &operation.signing,
   6281             expected.signing,
   6282         )?;
   6283         validate_post_operation_scalar(expected.key, "transport", &operation.transport, "none")?;
   6284         if !operation.deterministic {
   6285             return Err(format!(
   6286                 "post operation {} deterministic drift: expected true, got false",
   6287                 expected.key
   6288             ));
   6289         }
   6290         validate_post_operation_sequence(
   6291             expected.key,
   6292             "inputs",
   6293             &operation.inputs,
   6294             expected.inputs,
   6295         )?;
   6296         validate_post_operation_sequence(
   6297             expected.key,
   6298             "outputs",
   6299             &operation.outputs,
   6300             expected.outputs,
   6301         )?;
   6302         validate_post_operation_sequence(
   6303             expected.key,
   6304             "implementation.rust_modules",
   6305             &operation.implementation.rust_modules,
   6306             expected.rust_modules,
   6307         )?;
   6308         validate_post_operation_sequence(
   6309             expected.key,
   6310             "implementation.rust_types",
   6311             &operation.implementation.rust_types,
   6312             expected.rust_types,
   6313         )?;
   6314         validate_post_operation_scalar(
   6315             expected.key,
   6316             "conformance.vector",
   6317             &operation.conformance.vector,
   6318             POST_CONFORMANCE_VECTOR_RELATIVE,
   6319         )?;
   6320         validate_operation_case_kinds(operation, vector)?;
   6321         if !operation
   6322             .conformance
   6323             .case_kinds
   6324             .iter()
   6325             .map(String::as_str)
   6326             .eq(expected.case_kinds.iter().copied())
   6327         {
   6328             return Err(format!(
   6329                 "post operation {} conformance.case_kinds drift: expected {:?}, got {:?}",
   6330                 expected.key, expected.case_kinds, operation.conformance.case_kinds
   6331             ));
   6332         }
   6333         for case_kind in &operation.conformance.case_kinds {
   6334             if let Some(previous) = owners.insert(case_kind.as_str(), expected.key) {
   6335                 return Err(format!(
   6336                     "post conformance case kind {case_kind} is multiply claimed by {previous} and {}",
   6337                     expected.key
   6338                 ));
   6339             }
   6340         }
   6341     }
   6342 
   6343     let mut actual_inventory = BTreeMap::new();
   6344     for entry in &vector.vectors {
   6345         if actual_inventory
   6346             .insert(entry.id.as_str(), entry.kind.as_str())
   6347             .is_some()
   6348         {
   6349             return Err(format!(
   6350                 "post conformance vector inventory has duplicate id {}",
   6351                 entry.id
   6352             ));
   6353         }
   6354     }
   6355     for kind in actual_inventory.values() {
   6356         if !owners.contains_key(kind) {
   6357             return Err(format!(
   6358                 "post conformance vector kind {kind} is not claimed by exactly one operation"
   6359             ));
   6360         }
   6361     }
   6362     let expected_inventory = POST_VECTOR_EXPECTATIONS
   6363         .into_iter()
   6364         .collect::<BTreeMap<_, _>>();
   6365     if actual_inventory != expected_inventory {
   6366         return Err(format!(
   6367             "post conformance vector inventory drift: expected {:?}, got {:?}",
   6368             expected_inventory, actual_inventory
   6369         ));
   6370     }
   6371     Ok(())
   6372 }
   6373 
   6374 fn validate_post_operation_scalar(
   6375     operation_key: &str,
   6376     field: &str,
   6377     actual: &str,
   6378     expected: &str,
   6379 ) -> Result<(), String> {
   6380     if actual != expected {
   6381         return Err(format!(
   6382             "post operation {operation_key} {field} drift: expected {expected}, got {actual}"
   6383         ));
   6384     }
   6385     Ok(())
   6386 }
   6387 
   6388 fn validate_post_operation_sequence(
   6389     operation_key: &str,
   6390     field: &str,
   6391     actual: &[String],
   6392     expected: &[&str],
   6393 ) -> Result<(), String> {
   6394     if !actual
   6395         .iter()
   6396         .map(String::as_str)
   6397         .eq(expected.iter().copied())
   6398     {
   6399         return Err(format!(
   6400             "post operation {operation_key} {field} drift: expected {:?}, got {:?}",
   6401             expected, actual
   6402         ));
   6403     }
   6404     Ok(())
   6405 }
   6406 
   6407 fn validate_comment_operation_authority(
   6408     manifest: &OperationsContractManifest,
   6409     workspace_root: &Path,
   6410 ) -> Result<(), String> {
   6411     let vector = validate_conformance_vector_file(
   6412         &workspace_root.join(COMMENT_CONFORMANCE_VECTOR_RELATIVE),
   6413         &manifest.contract.version,
   6414     )?;
   6415     validate_comment_operation_inventory(manifest, &vector)
   6416 }
   6417 
   6418 fn validate_comment_operation_inventory(
   6419     manifest: &OperationsContractManifest,
   6420     vector: &ConformanceVectorFile,
   6421 ) -> Result<(), String> {
   6422     let shared_types = collect_non_empty_set(
   6423         &manifest.shared_types.public,
   6424         "comment operation shared_types.public",
   6425     )?;
   6426     for required in REQUIRED_COMMENT_PUBLIC_TYPES {
   6427         if !shared_types.contains(required) {
   6428             return Err(format!(
   6429                 "comment operation authority requires shared public type {required}"
   6430             ));
   6431         }
   6432     }
   6433 
   6434     let expected_keys = COMMENT_OPERATION_EXPECTATIONS
   6435         .iter()
   6436         .map(|expectation| expectation.key.to_string())
   6437         .collect::<BTreeSet<_>>();
   6438     let actual_keys = manifest
   6439         .operations
   6440         .iter()
   6441         .filter(|(key, operation)| {
   6442             operation.conformance.vector == COMMENT_CONFORMANCE_VECTOR_RELATIVE
   6443                 || key.starts_with("social_comment_")
   6444                 || operation.id.starts_with("social.comment.")
   6445         })
   6446         .map(|(key, _)| key.clone())
   6447         .collect::<BTreeSet<_>>();
   6448     if actual_keys != expected_keys {
   6449         let missing = expected_keys
   6450             .difference(&actual_keys)
   6451             .cloned()
   6452             .collect::<BTreeSet<_>>();
   6453         let unexpected = actual_keys
   6454             .difference(&expected_keys)
   6455             .cloned()
   6456             .collect::<BTreeSet<_>>();
   6457         return Err(format!(
   6458             "comment operation authority drift: missing {}; unexpected {}",
   6459             join_set(&missing),
   6460             join_set(&unexpected)
   6461         ));
   6462     }
   6463 
   6464     let mut owners = BTreeMap::new();
   6465     for expected in COMMENT_OPERATION_EXPECTATIONS {
   6466         let operation = manifest
   6467             .operations
   6468             .get(expected.key)
   6469             .ok_or_else(|| format!("comment operation {} is required", expected.key))?;
   6470         validate_comment_operation_scalar(expected.key, "domain", &operation.domain, "social")?;
   6471         validate_comment_operation_scalar(expected.key, "id", &operation.id, expected.id)?;
   6472         validate_comment_operation_scalar(expected.key, "stability", &operation.stability, "beta")?;
   6473         validate_comment_operation_scalar(
   6474             expected.key,
   6475             "error_class",
   6476             &operation.error_class,
   6477             expected.error_class,
   6478         )?;
   6479         validate_comment_operation_scalar(
   6480             expected.key,
   6481             "signing",
   6482             &operation.signing,
   6483             expected.signing,
   6484         )?;
   6485         validate_comment_operation_scalar(expected.key, "transport", &operation.transport, "none")?;
   6486         if !operation.deterministic {
   6487             return Err(format!(
   6488                 "comment operation {} deterministic drift: expected true, got false",
   6489                 expected.key
   6490             ));
   6491         }
   6492         validate_comment_operation_sequence(
   6493             expected.key,
   6494             "inputs",
   6495             &operation.inputs,
   6496             expected.inputs,
   6497         )?;
   6498         validate_comment_operation_sequence(
   6499             expected.key,
   6500             "outputs",
   6501             &operation.outputs,
   6502             expected.outputs,
   6503         )?;
   6504         validate_comment_operation_sequence(
   6505             expected.key,
   6506             "implementation.rust_modules",
   6507             &operation.implementation.rust_modules,
   6508             expected.rust_modules,
   6509         )?;
   6510         validate_comment_operation_sequence(
   6511             expected.key,
   6512             "implementation.rust_types",
   6513             &operation.implementation.rust_types,
   6514             expected.rust_types,
   6515         )?;
   6516         validate_comment_operation_scalar(
   6517             expected.key,
   6518             "conformance.vector",
   6519             &operation.conformance.vector,
   6520             COMMENT_CONFORMANCE_VECTOR_RELATIVE,
   6521         )?;
   6522         validate_operation_case_kinds(operation, vector)?;
   6523         if !operation
   6524             .conformance
   6525             .case_kinds
   6526             .iter()
   6527             .map(String::as_str)
   6528             .eq(expected.case_kinds.iter().copied())
   6529         {
   6530             return Err(format!(
   6531                 "comment operation {} conformance.case_kinds drift: expected {:?}, got {:?}",
   6532                 expected.key, expected.case_kinds, operation.conformance.case_kinds
   6533             ));
   6534         }
   6535         for case_kind in &operation.conformance.case_kinds {
   6536             if let Some(previous) = owners.insert(case_kind.as_str(), expected.key) {
   6537                 return Err(format!(
   6538                     "comment conformance case kind {case_kind} is multiply claimed by {previous} and {}",
   6539                     expected.key
   6540                 ));
   6541             }
   6542         }
   6543     }
   6544 
   6545     let expected_case_kinds = COMMENT_CASE_KINDS.into_iter().collect::<BTreeSet<_>>();
   6546     let actual_case_kinds = owners.keys().copied().collect::<BTreeSet<_>>();
   6547     if actual_case_kinds != expected_case_kinds {
   6548         return Err(format!(
   6549             "comment conformance case-kind authority drift: expected {:?}, got {:?}",
   6550             expected_case_kinds, actual_case_kinds
   6551         ));
   6552     }
   6553 
   6554     let mut actual_inventory = BTreeMap::new();
   6555     for entry in &vector.vectors {
   6556         if actual_inventory
   6557             .insert(entry.id.as_str(), entry.kind.as_str())
   6558             .is_some()
   6559         {
   6560             return Err(format!(
   6561                 "comment conformance vector inventory has duplicate id {}",
   6562                 entry.id
   6563             ));
   6564         }
   6565         if !owners.contains_key(entry.kind.as_str()) {
   6566             return Err(format!(
   6567                 "comment conformance vector kind {} is not claimed by exactly one operation",
   6568                 entry.kind
   6569             ));
   6570         }
   6571     }
   6572     let expected_inventory = COMMENT_VECTOR_EXPECTATIONS
   6573         .into_iter()
   6574         .collect::<BTreeMap<_, _>>();
   6575     if actual_inventory != expected_inventory {
   6576         return Err(format!(
   6577             "comment conformance vector inventory drift: expected {:?}, got {:?}",
   6578             expected_inventory, actual_inventory
   6579         ));
   6580     }
   6581 
   6582     Ok(())
   6583 }
   6584 
   6585 fn validate_comment_operation_scalar(
   6586     operation_key: &str,
   6587     field: &str,
   6588     actual: &str,
   6589     expected: &str,
   6590 ) -> Result<(), String> {
   6591     if actual != expected {
   6592         return Err(format!(
   6593             "comment operation {operation_key} {field} drift: expected {expected}, got {actual}"
   6594         ));
   6595     }
   6596     Ok(())
   6597 }
   6598 
   6599 fn validate_comment_operation_sequence(
   6600     operation_key: &str,
   6601     field: &str,
   6602     actual: &[String],
   6603     expected: &[&str],
   6604 ) -> Result<(), String> {
   6605     if !actual
   6606         .iter()
   6607         .map(String::as_str)
   6608         .eq(expected.iter().copied())
   6609     {
   6610         return Err(format!(
   6611             "comment operation {operation_key} {field} drift: expected {:?}, got {:?}",
   6612             expected, actual
   6613         ));
   6614     }
   6615     Ok(())
   6616 }
   6617 
   6618 fn validate_deletion_operation_authority(
   6619     manifest: &OperationsContractManifest,
   6620     workspace_root: &Path,
   6621 ) -> Result<(), String> {
   6622     let request_vector = validate_conformance_vector_file(
   6623         &workspace_root.join(DELETION_CONFORMANCE_VECTOR_RELATIVE),
   6624         &manifest.contract.version,
   6625     )?;
   6626     let suppression_vector = validate_conformance_vector_file(
   6627         &workspace_root.join(DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE),
   6628         &manifest.contract.version,
   6629     )?;
   6630     validate_deletion_operation_inventory(manifest, &request_vector, &suppression_vector)
   6631 }
   6632 
   6633 fn validate_deletion_operation_inventory(
   6634     manifest: &OperationsContractManifest,
   6635     request_vector: &ConformanceVectorFile,
   6636     suppression_vector: &ConformanceVectorFile,
   6637 ) -> Result<(), String> {
   6638     let shared_types = collect_non_empty_set(
   6639         &manifest.shared_types.public,
   6640         "deletion operation shared_types.public",
   6641     )?;
   6642     let expected_public_types = REQUIRED_DELETION_PUBLIC_TYPES
   6643         .into_iter()
   6644         .collect::<BTreeSet<_>>();
   6645     let actual_public_types = shared_types
   6646         .iter()
   6647         .map(String::as_str)
   6648         .filter(|name| {
   6649             name.contains("Nip09Deletion")
   6650                 || name.starts_with("RadrootsNip09")
   6651                 || name.starts_with("Nip01Coordinate")
   6652                 || matches!(
   6653                     *name,
   6654                     "Nip01EventWireParts" | "EventEnvelope" | "RadrootsSignatureVerifiedEvent"
   6655                 )
   6656         })
   6657         .collect::<BTreeSet<_>>();
   6658     if actual_public_types != expected_public_types {
   6659         return Err(format!(
   6660             "deletion operation public-type authority drift: expected {:?}, got {:?}",
   6661             expected_public_types, actual_public_types
   6662         ));
   6663     }
   6664 
   6665     let expected_keys = DELETION_OPERATION_EXPECTATIONS
   6666         .iter()
   6667         .map(|expectation| expectation.key.to_string())
   6668         .collect::<BTreeSet<_>>();
   6669     let actual_keys = manifest
   6670         .operations
   6671         .iter()
   6672         .filter(|(key, operation)| {
   6673             operation.conformance.vector == DELETION_CONFORMANCE_VECTOR_RELATIVE
   6674                 || operation.conformance.vector == DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE
   6675                 || key.starts_with("social_deletion_request_")
   6676                 || operation.id.starts_with("social.deletion_request.")
   6677         })
   6678         .map(|(key, _)| key.clone())
   6679         .collect::<BTreeSet<_>>();
   6680     if actual_keys != expected_keys {
   6681         let missing = expected_keys
   6682             .difference(&actual_keys)
   6683             .cloned()
   6684             .collect::<BTreeSet<_>>();
   6685         let unexpected = actual_keys
   6686             .difference(&expected_keys)
   6687             .cloned()
   6688             .collect::<BTreeSet<_>>();
   6689         return Err(format!(
   6690             "deletion operation authority drift: missing {}; unexpected {}",
   6691             join_set(&missing),
   6692             join_set(&unexpected)
   6693         ));
   6694     }
   6695 
   6696     let mut owners = BTreeMap::new();
   6697     for expected in DELETION_OPERATION_EXPECTATIONS {
   6698         let vector = match expected.vector {
   6699             DELETION_CONFORMANCE_VECTOR_RELATIVE => request_vector,
   6700             DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE => suppression_vector,
   6701             unexpected => {
   6702                 return Err(format!(
   6703                     "deletion operation authority contains unsupported vector {unexpected}"
   6704                 ));
   6705             }
   6706         };
   6707         let operation = manifest
   6708             .operations
   6709             .get(expected.key)
   6710             .ok_or_else(|| format!("deletion operation {} is required", expected.key))?;
   6711         validate_deletion_operation_scalar(expected.key, "domain", &operation.domain, "social")?;
   6712         validate_deletion_operation_scalar(expected.key, "id", &operation.id, expected.id)?;
   6713         validate_deletion_operation_scalar(
   6714             expected.key,
   6715             "stability",
   6716             &operation.stability,
   6717             "beta",
   6718         )?;
   6719         validate_deletion_operation_scalar(
   6720             expected.key,
   6721             "error_class",
   6722             &operation.error_class,
   6723             expected.error_class,
   6724         )?;
   6725         validate_deletion_operation_scalar(
   6726             expected.key,
   6727             "signing",
   6728             &operation.signing,
   6729             expected.signing,
   6730         )?;
   6731         validate_deletion_operation_scalar(
   6732             expected.key,
   6733             "transport",
   6734             &operation.transport,
   6735             "none",
   6736         )?;
   6737         if !operation.deterministic {
   6738             return Err(format!(
   6739                 "deletion operation {} deterministic drift: expected true, got false",
   6740                 expected.key
   6741             ));
   6742         }
   6743         validate_deletion_operation_sequence(
   6744             expected.key,
   6745             "inputs",
   6746             &operation.inputs,
   6747             expected.inputs,
   6748         )?;
   6749         validate_deletion_operation_sequence(
   6750             expected.key,
   6751             "outputs",
   6752             &operation.outputs,
   6753             expected.outputs,
   6754         )?;
   6755         validate_deletion_operation_sequence(
   6756             expected.key,
   6757             "implementation.rust_modules",
   6758             &operation.implementation.rust_modules,
   6759             expected.rust_modules,
   6760         )?;
   6761         validate_deletion_operation_sequence(
   6762             expected.key,
   6763             "implementation.rust_types",
   6764             &operation.implementation.rust_types,
   6765             expected.rust_types,
   6766         )?;
   6767         validate_deletion_operation_scalar(
   6768             expected.key,
   6769             "conformance.vector",
   6770             &operation.conformance.vector,
   6771             expected.vector,
   6772         )?;
   6773         validate_operation_case_kinds(operation, vector)?;
   6774         if !operation
   6775             .conformance
   6776             .case_kinds
   6777             .iter()
   6778             .map(String::as_str)
   6779             .eq(expected.case_kinds.iter().copied())
   6780         {
   6781             return Err(format!(
   6782                 "deletion operation {} conformance.case_kinds drift: expected {:?}, got {:?}",
   6783                 expected.key, expected.case_kinds, operation.conformance.case_kinds
   6784             ));
   6785         }
   6786         for case_kind in &operation.conformance.case_kinds {
   6787             if let Some(previous) = owners.insert(case_kind.as_str(), expected.key) {
   6788                 return Err(format!(
   6789                     "deletion conformance case kind {case_kind} is multiply claimed by {previous} and {}",
   6790                     expected.key
   6791                 ));
   6792             }
   6793         }
   6794     }
   6795 
   6796     let expected_case_kinds = DELETION_CASE_KINDS.into_iter().collect::<BTreeSet<_>>();
   6797     let actual_case_kinds = owners.keys().copied().collect::<BTreeSet<_>>();
   6798     if actual_case_kinds != expected_case_kinds {
   6799         return Err(format!(
   6800             "deletion conformance case-kind authority drift: expected {:?}, got {:?}",
   6801             expected_case_kinds, actual_case_kinds
   6802         ));
   6803     }
   6804 
   6805     let mut actual_inventory = BTreeMap::new();
   6806     for entry in &request_vector.vectors {
   6807         validate_deletion_vector_shape(entry)?;
   6808         if actual_inventory
   6809             .insert(entry.id.as_str(), entry.kind.as_str())
   6810             .is_some()
   6811         {
   6812             return Err(format!(
   6813                 "deletion conformance vector inventory has duplicate id {}",
   6814                 entry.id
   6815             ));
   6816         }
   6817         if !entry.id.starts_with("nip09_") {
   6818             return Err(format!(
   6819                 "deletion conformance vector id {} must use the nip09_ prefix",
   6820                 entry.id
   6821             ));
   6822         }
   6823         if !owners.contains_key(entry.kind.as_str()) {
   6824             return Err(format!(
   6825                 "deletion conformance vector kind {} is not claimed by exactly one operation",
   6826                 entry.kind
   6827             ));
   6828         }
   6829     }
   6830     let mut expected_inventory = BTreeMap::new();
   6831     for (ids, kind) in [
   6832         (
   6833             DELETION_AUTHORED_VALID_IDS.as_slice(),
   6834             "social.deletion_request.build_authored_draft.valid",
   6835         ),
   6836         (
   6837             DELETION_AUTHORED_INVALID_IDS.as_slice(),
   6838             "social.deletion_request.build_authored_draft.invalid",
   6839         ),
   6840         (
   6841             DELETION_PROJECT_VALID_IDS.as_slice(),
   6842             "social.deletion_request.project_verified_event.valid",
   6843         ),
   6844         (
   6845             DELETION_PROJECT_INVALID_IDS.as_slice(),
   6846             "social.deletion_request.project_verified_event.invalid",
   6847         ),
   6848         (
   6849             DELETION_ADMIT_VALID_IDS.as_slice(),
   6850             "social.deletion_request.verify_and_admit_event.valid",
   6851         ),
   6852         (
   6853             DELETION_ADMIT_INVALID_IDS.as_slice(),
   6854             "social.deletion_request.verify_and_admit_event.invalid",
   6855         ),
   6856     ] {
   6857         for id in ids {
   6858             if expected_inventory.insert(*id, kind).is_some() {
   6859                 return Err(format!(
   6860                     "deletion authority contains duplicate expected vector id {id}"
   6861                 ));
   6862             }
   6863         }
   6864     }
   6865     if actual_inventory != expected_inventory {
   6866         return Err(format!(
   6867             "deletion conformance vector inventory drift: expected {:?}, got {:?}",
   6868             expected_inventory, actual_inventory
   6869         ));
   6870     }
   6871 
   6872     validate_deletion_suppression_vector_inventory(suppression_vector, &owners)
   6873 }
   6874 
   6875 fn validate_deletion_suppression_vector_inventory(
   6876     vector: &ConformanceVectorFile,
   6877     owners: &BTreeMap<&str, &str>,
   6878 ) -> Result<(), String> {
   6879     if vector.suite != "nip09_suppression_evaluator" {
   6880         return Err(format!(
   6881             "deletion suppression conformance suite drift: expected nip09_suppression_evaluator, got {}",
   6882             vector.suite
   6883         ));
   6884     }
   6885 
   6886     let expected_kind = "social.deletion_request.evaluate_suppression.valid";
   6887     if owners.get(expected_kind).copied() != Some("social_deletion_request_evaluate_suppression") {
   6888         return Err(format!(
   6889             "deletion suppression conformance kind {expected_kind} is not owned by the evaluator operation"
   6890         ));
   6891     }
   6892 
   6893     let expected_inventory = DELETION_SUPPRESSION_VALID_IDS
   6894         .into_iter()
   6895         .map(|id| (id, expected_kind))
   6896         .collect::<BTreeMap<_, _>>();
   6897     let mut actual_inventory = BTreeMap::new();
   6898     for entry in &vector.vectors {
   6899         validate_deletion_suppression_vector_shape(entry)?;
   6900         if actual_inventory
   6901             .insert(entry.id.as_str(), entry.kind.as_str())
   6902             .is_some()
   6903         {
   6904             return Err(format!(
   6905                 "deletion suppression conformance vector inventory has duplicate id {}",
   6906                 entry.id
   6907             ));
   6908         }
   6909         if !entry.id.starts_with("nip09_suppress_") {
   6910             return Err(format!(
   6911                 "deletion suppression conformance vector id {} must use the nip09_suppress_ prefix",
   6912                 entry.id
   6913             ));
   6914         }
   6915         if entry.kind != expected_kind {
   6916             return Err(format!(
   6917                 "deletion suppression conformance vector {} kind drift: expected {expected_kind}, got {}",
   6918                 entry.id, entry.kind
   6919             ));
   6920         }
   6921     }
   6922     if actual_inventory != expected_inventory {
   6923         return Err(format!(
   6924             "deletion suppression conformance vector inventory drift: expected {:?}, got {:?}",
   6925             expected_inventory, actual_inventory
   6926         ));
   6927     }
   6928 
   6929     Ok(())
   6930 }
   6931 
   6932 fn validate_deletion_suppression_vector_shape(
   6933     entry: &ConformanceVectorEntry,
   6934 ) -> Result<(), String> {
   6935     validate_deletion_suppression_forbidden_material(&entry.input, &format!("{}.input", entry.id))?;
   6936     let expected_value = entry.expected_value()?;
   6937     validate_deletion_suppression_forbidden_material(
   6938         expected_value,
   6939         &format!("{}.expected", entry.id),
   6940     )?;
   6941 
   6942     let input = deletion_object(&entry.input, &format!("{} input", entry.id))?;
   6943     validate_deletion_object_keys(
   6944         input,
   6945         &format!("{} input", entry.id),
   6946         &["request_event_jsons", "target_event_json"],
   6947     )?;
   6948     let target_event_json = input
   6949         .get("target_event_json")
   6950         .and_then(Value::as_str)
   6951         .ok_or_else(|| {
   6952             format!(
   6953                 "deletion suppression vector {} input.target_event_json must be a string",
   6954                 entry.id
   6955             )
   6956         })?;
   6957     validate_deletion_suppression_fixed_event(
   6958         target_event_json,
   6959         &format!("{} target_event_json", entry.id),
   6960         None,
   6961     )?;
   6962 
   6963     let request_event_jsons = input
   6964         .get("request_event_jsons")
   6965         .and_then(Value::as_array)
   6966         .ok_or_else(|| {
   6967             format!(
   6968                 "deletion suppression vector {} input.request_event_jsons must be an array",
   6969                 entry.id
   6970             )
   6971         })?;
   6972     let mut request_ids = BTreeSet::new();
   6973     for (index, value) in request_event_jsons.iter().enumerate() {
   6974         let event_json = value.as_str().ok_or_else(|| {
   6975             format!(
   6976                 "deletion suppression vector {} input.request_event_jsons[{index}] must be a string",
   6977                 entry.id
   6978             )
   6979         })?;
   6980         let event = validate_deletion_suppression_fixed_event(
   6981             event_json,
   6982             &format!("{} request_event_jsons[{index}]", entry.id),
   6983             Some(5),
   6984         )?;
   6985         request_ids.insert(event.id);
   6986     }
   6987 
   6988     let expected = deletion_object(expected_value, &format!("{} expected", entry.id))?;
   6989     validate_deletion_object_keys(
   6990         expected,
   6991         &format!("{} expected", entry.id),
   6992         &["address_reference", "event_reference", "outcome", "reason"],
   6993     )?;
   6994     let outcome = expected
   6995         .get("outcome")
   6996         .and_then(Value::as_str)
   6997         .ok_or_else(|| {
   6998             format!(
   6999                 "deletion suppression vector {} expected.outcome must be a string",
   7000                 entry.id
   7001             )
   7002         })?;
   7003     if !matches!(outcome, "visible" | "suppressed") {
   7004         return Err(format!(
   7005             "deletion suppression vector {} expected.outcome is unsupported: {outcome}",
   7006             entry.id
   7007         ));
   7008     }
   7009     let reason = expected
   7010         .get("reason")
   7011         .and_then(Value::as_str)
   7012         .ok_or_else(|| {
   7013             format!(
   7014                 "deletion suppression vector {} expected.reason must be a string",
   7015                 entry.id
   7016             )
   7017         })?;
   7018     if !matches!(
   7019         reason,
   7020         "deletion_request_immune"
   7021             | "deletion_no_authorized_reference"
   7022             | "deletion_request_author_mismatch"
   7023             | "deletion_address_cutoff_precedes_target"
   7024             | "deletion_event_id_reference"
   7025             | "deletion_address_reference"
   7026             | "deletion_event_id_and_address_reference"
   7027     ) {
   7028         return Err(format!(
   7029             "deletion suppression vector {} expected.reason is unsupported: {reason}",
   7030             entry.id
   7031         ));
   7032     }
   7033 
   7034     let event_reference = validate_deletion_suppression_event_reference(
   7035         expected
   7036             .get("event_reference")
   7037             .expect("exact expected keys contain event_reference"),
   7038         &entry.id,
   7039         &request_ids,
   7040     )?;
   7041     let address_reference = validate_deletion_suppression_address_reference(
   7042         expected
   7043             .get("address_reference")
   7044             .expect("exact expected keys contain address_reference"),
   7045         &entry.id,
   7046         &request_ids,
   7047     )?;
   7048     let decision_shape_matches = match reason {
   7049         "deletion_request_immune"
   7050         | "deletion_no_authorized_reference"
   7051         | "deletion_request_author_mismatch" => {
   7052             outcome == "visible" && !event_reference && !address_reference
   7053         }
   7054         "deletion_address_cutoff_precedes_target" => {
   7055             outcome == "visible" && !event_reference && address_reference
   7056         }
   7057         "deletion_address_reference" => {
   7058             outcome == "suppressed" && !event_reference && address_reference
   7059         }
   7060         "deletion_event_id_and_address_reference" => {
   7061             outcome == "suppressed" && event_reference && address_reference
   7062         }
   7063         "deletion_event_id_reference" => outcome == "suppressed" && event_reference,
   7064         _ => unreachable!("supported reason matched above"),
   7065     };
   7066     if !decision_shape_matches {
   7067         return Err(format!(
   7068             "deletion suppression vector {} expected decision shape is inconsistent with reason {reason}",
   7069             entry.id
   7070         ));
   7071     }
   7072 
   7073     Ok(())
   7074 }
   7075 
   7076 fn validate_deletion_suppression_fixed_event(
   7077     event_json: &str,
   7078     label: &str,
   7079     expected_kind: Option<u32>,
   7080 ) -> Result<DeletionConformanceRawEvent, String> {
   7081     if contains_nsec_material(event_json) {
   7082         return Err(format!(
   7083             "deletion suppression vector {label} contains forbidden nsec material"
   7084         ));
   7085     }
   7086     if contains_approved_fixture_secret(event_json) {
   7087         return Err(format!(
   7088             "deletion suppression vector {label} contains forbidden approved fixture secret material"
   7089         ));
   7090     }
   7091     let raw = serde_json::from_str::<DeletionConformanceRawEvent>(event_json).map_err(|error| {
   7092         format!("deletion suppression vector {label} has invalid fixed event shape: {error}")
   7093     })?;
   7094     if expected_kind.is_some_and(|kind| raw.kind != kind) {
   7095         return Err(format!(
   7096             "deletion suppression vector {label} must contain a kind-5 deletion request"
   7097         ));
   7098     }
   7099     let canonical = serde_json::to_string(&raw).map_err(|error| {
   7100         format!("deletion suppression vector {label} cannot be reserialized: {error}")
   7101     })?;
   7102     if canonical != event_json {
   7103         return Err(format!(
   7104             "deletion suppression vector {label} must be compact canonical JSON"
   7105         ));
   7106     }
   7107     Ok(raw)
   7108 }
   7109 
   7110 fn validate_deletion_suppression_event_reference(
   7111     value: &Value,
   7112     id: &str,
   7113     request_ids: &BTreeSet<String>,
   7114 ) -> Result<bool, String> {
   7115     if value.is_null() {
   7116         return Ok(false);
   7117     }
   7118     let reference = deletion_object(value, &format!("{id} expected.event_reference"))?;
   7119     validate_deletion_object_keys(
   7120         reference,
   7121         &format!("{id} expected.event_reference"),
   7122         &["request_id"],
   7123     )?;
   7124     validate_deletion_suppression_request_id(
   7125         reference.get("request_id"),
   7126         id,
   7127         "event_reference.request_id",
   7128         request_ids,
   7129     )?;
   7130     Ok(true)
   7131 }
   7132 
   7133 fn validate_deletion_suppression_address_reference(
   7134     value: &Value,
   7135     id: &str,
   7136     request_ids: &BTreeSet<String>,
   7137 ) -> Result<bool, String> {
   7138     if value.is_null() {
   7139         return Ok(false);
   7140     }
   7141     let reference = deletion_object(value, &format!("{id} expected.address_reference"))?;
   7142     validate_deletion_object_keys(
   7143         reference,
   7144         &format!("{id} expected.address_reference"),
   7145         &["coordinate", "inclusive_cutoff", "request_id"],
   7146     )?;
   7147     let coordinate = reference
   7148         .get("coordinate")
   7149         .and_then(Value::as_str)
   7150         .ok_or_else(|| {
   7151             format!(
   7152                 "deletion suppression vector {id} expected.address_reference.coordinate must be a string"
   7153             )
   7154         })?;
   7155     validate_deletion_suppression_coordinate(coordinate, id)?;
   7156     if !reference
   7157         .get("inclusive_cutoff")
   7158         .is_some_and(|value| value.as_u64().is_some())
   7159     {
   7160         return Err(format!(
   7161             "deletion suppression vector {id} expected.address_reference.inclusive_cutoff must be an unsigned integer"
   7162         ));
   7163     }
   7164     validate_deletion_suppression_request_id(
   7165         reference.get("request_id"),
   7166         id,
   7167         "address_reference.request_id",
   7168         request_ids,
   7169     )?;
   7170     Ok(true)
   7171 }
   7172 
   7173 fn validate_deletion_suppression_request_id(
   7174     value: Option<&Value>,
   7175     id: &str,
   7176     field: &str,
   7177     request_ids: &BTreeSet<String>,
   7178 ) -> Result<(), String> {
   7179     let request_id = value.and_then(Value::as_str).ok_or_else(|| {
   7180         format!("deletion suppression vector {id} expected.{field} must be a string")
   7181     })?;
   7182     if request_id.len() != 64
   7183         || !request_id
   7184             .bytes()
   7185             .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
   7186     {
   7187         return Err(format!(
   7188             "deletion suppression vector {id} expected.{field} must be lowercase 64-character hex"
   7189         ));
   7190     }
   7191     if !request_ids.contains(request_id) {
   7192         return Err(format!(
   7193             "deletion suppression vector {id} expected.{field} must identify an input request"
   7194         ));
   7195     }
   7196     Ok(())
   7197 }
   7198 
   7199 fn validate_deletion_suppression_coordinate(coordinate: &str, id: &str) -> Result<(), String> {
   7200     let mut parts = coordinate.splitn(3, ':');
   7201     let kind_text = parts.next().unwrap_or_default();
   7202     let pubkey = parts.next().unwrap_or_default();
   7203     let identifier = parts.next().ok_or_else(|| {
   7204         format!(
   7205             "deletion suppression vector {id} expected.address_reference.coordinate has invalid format"
   7206         )
   7207     })?;
   7208     let kind = kind_text.parse::<u32>().map_err(|_| {
   7209         format!(
   7210             "deletion suppression vector {id} expected.address_reference.coordinate kind is invalid"
   7211         )
   7212     })?;
   7213     if kind.to_string() != kind_text
   7214         || pubkey.len() != 64
   7215         || !pubkey
   7216             .bytes()
   7217             .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
   7218         || (!matches!(kind, 0 | 3)
   7219             && !(10_000..=19_999).contains(&kind)
   7220             && !(30_000..=39_999).contains(&kind))
   7221         || ((matches!(kind, 0 | 3) || (10_000..=19_999).contains(&kind)) && !identifier.is_empty())
   7222     {
   7223         return Err(format!(
   7224             "deletion suppression vector {id} expected.address_reference.coordinate is not canonical"
   7225         ));
   7226     }
   7227     Ok(())
   7228 }
   7229 
   7230 fn validate_deletion_suppression_forbidden_material(
   7231     value: &Value,
   7232     path: &str,
   7233 ) -> Result<(), String> {
   7234     match value {
   7235         Value::Object(object) => {
   7236             for (key, child) in object {
   7237                 let normalized = key.to_ascii_lowercase();
   7238                 if matches!(normalized.as_str(), "base" | "mutation")
   7239                     || normalized.contains("seed")
   7240                     || normalized.contains("generator")
   7241                     || normalized.contains("recipe")
   7242                     || normalized.contains("secret_key")
   7243                     || normalized.contains("private_key")
   7244                     || normalized.contains("signing_key")
   7245                     || normalized.contains("boundary")
   7246                 {
   7247                     return Err(format!(
   7248                         "deletion suppression vector contains forbidden metadata key {path}.{key}"
   7249                     ));
   7250                 }
   7251                 validate_deletion_suppression_forbidden_material(child, &format!("{path}.{key}"))?;
   7252             }
   7253         }
   7254         Value::Array(values) => {
   7255             for (index, child) in values.iter().enumerate() {
   7256                 validate_deletion_suppression_forbidden_material(
   7257                     child,
   7258                     &format!("{path}[{index}]"),
   7259                 )?;
   7260             }
   7261         }
   7262         Value::String(string) => {
   7263             if contains_nsec_material(string) {
   7264                 return Err(format!(
   7265                     "deletion suppression vector contains forbidden nsec material at {path}"
   7266                 ));
   7267             }
   7268             if contains_approved_fixture_secret(string) {
   7269                 return Err(format!(
   7270                     "deletion suppression vector contains forbidden approved fixture secret material at {path}"
   7271                 ));
   7272             }
   7273         }
   7274         _ => {}
   7275     }
   7276     Ok(())
   7277 }
   7278 
   7279 fn validate_deletion_vector_shape(entry: &ConformanceVectorEntry) -> Result<(), String> {
   7280     validate_deletion_forbidden_metadata(&entry.input, &format!("{}.input", entry.id))?;
   7281     let expected_value = entry.expected_value()?;
   7282     validate_deletion_forbidden_metadata(expected_value, &format!("{}.expected", entry.id))?;
   7283 
   7284     let input = deletion_object(&entry.input, &format!("{} input", entry.id))?;
   7285     let is_authored = entry
   7286         .kind
   7287         .starts_with("social.deletion_request.build_authored_draft.");
   7288     let is_valid = entry.kind.ends_with(".valid");
   7289     if is_authored {
   7290         validate_deletion_object_keys(
   7291             input,
   7292             &format!("{} input", entry.id),
   7293             &["address_targets", "content", "event_targets"],
   7294         )?;
   7295         if !input.get("content").is_some_and(Value::is_string) {
   7296             return Err(format!(
   7297                 "deletion vector {} input.content must be a string",
   7298                 entry.id
   7299             ));
   7300         }
   7301         let event_targets = input
   7302             .get("event_targets")
   7303             .and_then(Value::as_array)
   7304             .ok_or_else(|| {
   7305                 format!(
   7306                     "deletion vector {} input.event_targets must be an array",
   7307                     entry.id
   7308                 )
   7309             })?;
   7310         for (index, target) in event_targets.iter().enumerate() {
   7311             let target = deletion_object(
   7312                 target,
   7313                 &format!("{} input.event_targets[{index}]", entry.id),
   7314             )?;
   7315             validate_deletion_object_keys(
   7316                 target,
   7317                 &format!("{} input.event_targets[{index}]", entry.id),
   7318                 &["event_id", "kind"],
   7319             )?;
   7320             if !target.get("event_id").is_some_and(Value::is_string)
   7321                 || !target.get("kind").is_some_and(Value::is_u64)
   7322             {
   7323                 return Err(format!(
   7324                     "deletion vector {} input.event_targets[{index}] must contain string event_id and unsigned kind",
   7325                     entry.id
   7326                 ));
   7327             }
   7328         }
   7329         let address_targets = input
   7330             .get("address_targets")
   7331             .and_then(Value::as_array)
   7332             .ok_or_else(|| {
   7333                 format!(
   7334                     "deletion vector {} input.address_targets must be an array",
   7335                     entry.id
   7336                 )
   7337             })?;
   7338         if !address_targets.iter().all(Value::is_string) {
   7339             return Err(format!(
   7340                 "deletion vector {} input.address_targets must contain only strings",
   7341                 entry.id
   7342             ));
   7343         }
   7344     } else {
   7345         validate_deletion_object_keys(input, &format!("{} input", entry.id), &["event_json"])?;
   7346         let event_json = input
   7347             .get("event_json")
   7348             .and_then(Value::as_str)
   7349             .ok_or_else(|| {
   7350                 format!(
   7351                     "deletion vector {} input.event_json must be a string",
   7352                     entry.id
   7353                 )
   7354             })?;
   7355         if contains_nsec_material(event_json) {
   7356             return Err(format!(
   7357                 "deletion vector {} input.event_json contains forbidden nsec material",
   7358                 entry.id
   7359             ));
   7360         }
   7361         let raw =
   7362             serde_json::from_str::<DeletionConformanceRawEvent>(event_json).map_err(|error| {
   7363                 format!(
   7364                     "deletion vector {} input.event_json has invalid fixed event shape: {error}",
   7365                     entry.id
   7366                 )
   7367             })?;
   7368         let canonical = serde_json::to_string(&raw).map_err(|error| {
   7369             format!(
   7370                 "deletion vector {} input.event_json cannot be reserialized: {error}",
   7371                 entry.id
   7372             )
   7373         })?;
   7374         if canonical != event_json {
   7375             return Err(format!(
   7376                 "deletion vector {} input.event_json must be compact canonical JSON",
   7377                 entry.id
   7378             ));
   7379         }
   7380     }
   7381 
   7382     let expected = deletion_object(expected_value, &format!("{} expected", entry.id))?;
   7383     if !is_valid {
   7384         validate_deletion_object_keys(expected, &format!("{} expected", entry.id), &["error"])?;
   7385         if !expected
   7386             .get("error")
   7387             .and_then(Value::as_str)
   7388             .is_some_and(|error| !error.is_empty())
   7389         {
   7390             return Err(format!(
   7391                 "deletion vector {} expected.error must be a non-empty string",
   7392                 entry.id
   7393             ));
   7394         }
   7395     } else if is_authored {
   7396         validate_deletion_object_keys(
   7397             expected,
   7398             &format!("{} expected", entry.id),
   7399             &["content", "kind", "tags"],
   7400         )?;
   7401         if expected.get("kind").and_then(Value::as_u64) != Some(5)
   7402             || !expected.get("content").is_some_and(Value::is_string)
   7403             || !expected.get("tags").is_some_and(Value::is_array)
   7404         {
   7405             return Err(format!(
   7406                 "deletion vector {} authored expected output must contain kind 5, string content, and tags",
   7407                 entry.id
   7408             ));
   7409         }
   7410     } else {
   7411         validate_deletion_object_keys(
   7412             expected,
   7413             &format!("{} expected", entry.id),
   7414             &[
   7415                 "address_targets",
   7416                 "contract_id",
   7417                 "diagnostics",
   7418                 "event_targets",
   7419                 "kind_advisories",
   7420                 "raw_tags",
   7421             ],
   7422         )?;
   7423         if expected.get("contract_id").and_then(Value::as_str)
   7424             != Some("radroots.social.deletion_request.v1")
   7425         {
   7426             return Err(format!(
   7427                 "deletion vector {} expected.contract_id drifted",
   7428                 entry.id
   7429             ));
   7430         }
   7431         for field in [
   7432             "address_targets",
   7433             "diagnostics",
   7434             "event_targets",
   7435             "kind_advisories",
   7436             "raw_tags",
   7437         ] {
   7438             if !expected.get(field).is_some_and(Value::is_array) {
   7439                 return Err(format!(
   7440                     "deletion vector {} expected.{field} must be an array",
   7441                     entry.id
   7442                 ));
   7443             }
   7444         }
   7445     }
   7446 
   7447     Ok(())
   7448 }
   7449 
   7450 const APPROVED_FIXTURE_SECRET_TEXT_SHA256: [&str; 4] = [
   7451     "abd5b64bb0a9a0b9b2e928edb278d0f4d442d16e620ac56570c354a040f4e01a",
   7452     "619b2fc89e98c17205800071802b3f06e12b05b79401da800b8b13aa8597d240",
   7453     "82e759d54455fbfa5b9c58367b37f1fbc3d54becc097dcdf71fa48ee0af6b2a6",
   7454     "510b06b0d391a517860b8e406cdc827b0481f2e449c9817b73adad07f4ff02a7",
   7455 ];
   7456 
   7457 fn validate_deletion_forbidden_metadata(value: &Value, path: &str) -> Result<(), String> {
   7458     match value {
   7459         Value::Object(object) => {
   7460             for (key, child) in object {
   7461                 if is_deletion_forbidden_metadata_key(key) {
   7462                     return Err(format!(
   7463                         "deletion vector contains forbidden metadata key {path}.{key}"
   7464                     ));
   7465                 }
   7466                 validate_deletion_forbidden_metadata(child, &format!("{path}.{key}"))?;
   7467             }
   7468         }
   7469         Value::Array(values) => {
   7470             for (index, child) in values.iter().enumerate() {
   7471                 validate_deletion_forbidden_metadata(child, &format!("{path}[{index}]"))?;
   7472             }
   7473         }
   7474         Value::String(string) => {
   7475             if contains_nsec_material(string) {
   7476                 return Err(format!(
   7477                     "deletion vector contains forbidden nsec material at {path}"
   7478                 ));
   7479             }
   7480             if contains_approved_fixture_secret(string) {
   7481                 return Err(format!(
   7482                     "deletion vector contains forbidden approved fixture secret material at {path}"
   7483                 ));
   7484             }
   7485         }
   7486         _ => {}
   7487     }
   7488     Ok(())
   7489 }
   7490 
   7491 fn is_deletion_forbidden_metadata_key(key: &str) -> bool {
   7492     let normalized = key.to_ascii_lowercase();
   7493     matches!(normalized.as_str(), "base" | "mutation")
   7494         || normalized.contains("seed")
   7495         || normalized.contains("generator")
   7496         || normalized.contains("recipe")
   7497         || normalized.contains("secret_key")
   7498         || normalized.contains("private_key")
   7499         || normalized.contains("signing_key")
   7500         || normalized.contains("boundary")
   7501         || normalized.contains("authorization")
   7502         || normalized.contains("authorized")
   7503         || normalized.contains("cutoff")
   7504         || normalized.contains("evaluator")
   7505         || normalized.contains("store_mutation")
   7506         || normalized.contains("suppression")
   7507         || normalized.contains("suppressed")
   7508         || normalized == "effect"
   7509         || normalized.ends_with("_effect")
   7510         || normalized == "effects"
   7511 }
   7512 
   7513 fn contains_nsec_material(value: &str) -> bool {
   7514     value.to_ascii_lowercase().contains("nsec1")
   7515 }
   7516 
   7517 fn contains_approved_fixture_secret(value: &str) -> bool {
   7518     value
   7519         .to_ascii_lowercase()
   7520         .as_bytes()
   7521         .windows(64)
   7522         .filter(|window| window.iter().all(u8::is_ascii_hexdigit))
   7523         .any(|window| {
   7524             let digest = hex::encode(Sha256::digest(window));
   7525             APPROVED_FIXTURE_SECRET_TEXT_SHA256.contains(&digest.as_str())
   7526         })
   7527 }
   7528 
   7529 fn deletion_object<'a>(
   7530     value: &'a Value,
   7531     label: &str,
   7532 ) -> Result<&'a serde_json::Map<String, Value>, String> {
   7533     value
   7534         .as_object()
   7535         .ok_or_else(|| format!("deletion vector {label} must be an object"))
   7536 }
   7537 
   7538 fn validate_deletion_object_keys(
   7539     object: &serde_json::Map<String, Value>,
   7540     label: &str,
   7541     expected: &[&str],
   7542 ) -> Result<(), String> {
   7543     let actual = object.keys().map(String::as_str).collect::<BTreeSet<_>>();
   7544     let expected = expected.iter().copied().collect::<BTreeSet<_>>();
   7545     if actual != expected {
   7546         return Err(format!(
   7547             "deletion vector {label} keys drift: expected {:?}, got {:?}",
   7548             expected, actual
   7549         ));
   7550     }
   7551     Ok(())
   7552 }
   7553 
   7554 fn validate_deletion_operation_scalar(
   7555     operation_key: &str,
   7556     field: &str,
   7557     actual: &str,
   7558     expected: &str,
   7559 ) -> Result<(), String> {
   7560     if actual != expected {
   7561         return Err(format!(
   7562             "deletion operation {operation_key} {field} drift: expected {expected}, got {actual}"
   7563         ));
   7564     }
   7565     Ok(())
   7566 }
   7567 
   7568 fn validate_deletion_operation_sequence(
   7569     operation_key: &str,
   7570     field: &str,
   7571     actual: &[String],
   7572     expected: &[&str],
   7573 ) -> Result<(), String> {
   7574     if !actual
   7575         .iter()
   7576         .map(String::as_str)
   7577         .eq(expected.iter().copied())
   7578     {
   7579         return Err(format!(
   7580             "deletion operation {operation_key} {field} drift: expected {:?}, got {:?}",
   7581             expected, actual
   7582         ));
   7583     }
   7584     Ok(())
   7585 }
   7586 
   7587 fn validate_food_availability_operation_authority(
   7588     manifest: &OperationsContractManifest,
   7589     workspace_root: &Path,
   7590 ) -> Result<(), String> {
   7591     let vector = validate_conformance_vector_file(
   7592         &workspace_root.join(FOOD_AVAILABILITY_CONFORMANCE_VECTOR_RELATIVE),
   7593         &manifest.contract.version,
   7594     )?;
   7595     validate_food_availability_operation_inventory(manifest, &vector)
   7596 }
   7597 
   7598 fn validate_food_availability_operation_inventory(
   7599     manifest: &OperationsContractManifest,
   7600     vector: &ConformanceVectorFile,
   7601 ) -> Result<(), String> {
   7602     let shared_types = collect_non_empty_set(
   7603         &manifest.shared_types.public,
   7604         "food availability operation shared_types.public",
   7605     )?;
   7606     for required in REQUIRED_FOOD_AVAILABILITY_PUBLIC_TYPES {
   7607         if !shared_types.contains(required) {
   7608             return Err(format!(
   7609                 "food availability operation authority requires shared public type {required}"
   7610             ));
   7611         }
   7612     }
   7613 
   7614     let expected_keys = FOOD_AVAILABILITY_OPERATION_EXPECTATIONS
   7615         .iter()
   7616         .map(|expectation| expectation.key.to_string())
   7617         .collect::<BTreeSet<_>>();
   7618     let actual_keys = manifest
   7619         .operations
   7620         .iter()
   7621         .filter(|(key, operation)| {
   7622             operation.domain == "food_availability"
   7623                 || operation.conformance.vector == FOOD_AVAILABILITY_CONFORMANCE_VECTOR_RELATIVE
   7624                 || key.starts_with("food_availability_")
   7625                 || operation.id.starts_with("food_availability.")
   7626         })
   7627         .map(|(key, _)| key.clone())
   7628         .collect::<BTreeSet<_>>();
   7629     if actual_keys != expected_keys {
   7630         let missing = expected_keys
   7631             .difference(&actual_keys)
   7632             .cloned()
   7633             .collect::<BTreeSet<_>>();
   7634         let unexpected = actual_keys
   7635             .difference(&expected_keys)
   7636             .cloned()
   7637             .collect::<BTreeSet<_>>();
   7638         return Err(format!(
   7639             "food availability operation authority drift: missing {}; unexpected {}",
   7640             join_set(&missing),
   7641             join_set(&unexpected)
   7642         ));
   7643     }
   7644 
   7645     let mut owners = BTreeMap::new();
   7646     for expected in FOOD_AVAILABILITY_OPERATION_EXPECTATIONS {
   7647         let operation = manifest
   7648             .operations
   7649             .get(expected.key)
   7650             .ok_or_else(|| format!("food availability operation {} is required", expected.key))?;
   7651         validate_food_availability_operation_scalar(
   7652             expected.key,
   7653             "domain",
   7654             &operation.domain,
   7655             "food_availability",
   7656         )?;
   7657         validate_food_availability_operation_scalar(
   7658             expected.key,
   7659             "id",
   7660             &operation.id,
   7661             expected.id,
   7662         )?;
   7663         validate_food_availability_operation_scalar(
   7664             expected.key,
   7665             "stability",
   7666             &operation.stability,
   7667             "beta",
   7668         )?;
   7669         validate_food_availability_operation_scalar(
   7670             expected.key,
   7671             "error_class",
   7672             &operation.error_class,
   7673             expected.error_class,
   7674         )?;
   7675         validate_food_availability_operation_scalar(
   7676             expected.key,
   7677             "signing",
   7678             &operation.signing,
   7679             expected.signing,
   7680         )?;
   7681         validate_food_availability_operation_scalar(
   7682             expected.key,
   7683             "transport",
   7684             &operation.transport,
   7685             "none",
   7686         )?;
   7687         if !operation.deterministic {
   7688             return Err(format!(
   7689                 "food availability operation {} deterministic drift: expected true, got false",
   7690                 expected.key
   7691             ));
   7692         }
   7693         validate_food_availability_operation_sequence(
   7694             expected.key,
   7695             "inputs",
   7696             &operation.inputs,
   7697             expected.inputs,
   7698         )?;
   7699         validate_food_availability_operation_sequence(
   7700             expected.key,
   7701             "outputs",
   7702             &operation.outputs,
   7703             expected.outputs,
   7704         )?;
   7705         validate_food_availability_operation_sequence(
   7706             expected.key,
   7707             "implementation.rust_modules",
   7708             &operation.implementation.rust_modules,
   7709             expected.rust_modules,
   7710         )?;
   7711         validate_food_availability_operation_sequence(
   7712             expected.key,
   7713             "implementation.rust_types",
   7714             &operation.implementation.rust_types,
   7715             expected.rust_types,
   7716         )?;
   7717         validate_food_availability_operation_scalar(
   7718             expected.key,
   7719             "conformance.vector",
   7720             &operation.conformance.vector,
   7721             FOOD_AVAILABILITY_CONFORMANCE_VECTOR_RELATIVE,
   7722         )?;
   7723         validate_operation_case_kinds(operation, vector)?;
   7724         if !operation
   7725             .conformance
   7726             .case_kinds
   7727             .iter()
   7728             .map(String::as_str)
   7729             .eq(expected.case_kinds.iter().copied())
   7730         {
   7731             return Err(format!(
   7732                 "food availability operation {} conformance.case_kinds drift: expected {:?}, got {:?}",
   7733                 expected.key, expected.case_kinds, operation.conformance.case_kinds
   7734             ));
   7735         }
   7736         for case_kind in &operation.conformance.case_kinds {
   7737             if let Some(previous) = owners.insert(case_kind.as_str(), expected.key) {
   7738                 return Err(format!(
   7739                     "food availability conformance case kind {case_kind} is multiply claimed by {previous} and {}",
   7740                     expected.key
   7741                 ));
   7742             }
   7743         }
   7744     }
   7745 
   7746     let expected_case_kinds = FOOD_AVAILABILITY_CASE_KINDS
   7747         .into_iter()
   7748         .collect::<BTreeSet<_>>();
   7749     let actual_case_kinds = owners.keys().copied().collect::<BTreeSet<_>>();
   7750     if actual_case_kinds != expected_case_kinds {
   7751         return Err(format!(
   7752             "food availability conformance case-kind authority drift: expected {:?}, got {:?}",
   7753             expected_case_kinds, actual_case_kinds
   7754         ));
   7755     }
   7756 
   7757     let mut actual_inventory = BTreeMap::new();
   7758     for entry in &vector.vectors {
   7759         if actual_inventory
   7760             .insert(entry.id.as_str(), entry.kind.as_str())
   7761             .is_some()
   7762         {
   7763             return Err(format!(
   7764                 "food availability conformance vector inventory has duplicate id {}",
   7765                 entry.id
   7766             ));
   7767         }
   7768     }
   7769     for kind in actual_inventory.values() {
   7770         if !owners.contains_key(kind) {
   7771             return Err(format!(
   7772                 "food availability conformance vector kind {kind} is not claimed by exactly one operation"
   7773             ));
   7774         }
   7775     }
   7776     let expected_inventory = FOOD_AVAILABILITY_VECTOR_EXPECTATIONS
   7777         .into_iter()
   7778         .collect::<BTreeMap<_, _>>();
   7779     if actual_inventory != expected_inventory {
   7780         return Err(format!(
   7781             "food availability conformance vector inventory drift: expected {:?}, got {:?}",
   7782             expected_inventory, actual_inventory
   7783         ));
   7784     }
   7785     Ok(())
   7786 }
   7787 
   7788 fn validate_food_availability_operation_scalar(
   7789     operation_key: &str,
   7790     field: &str,
   7791     actual: &str,
   7792     expected: &str,
   7793 ) -> Result<(), String> {
   7794     if actual != expected {
   7795         return Err(format!(
   7796             "food availability operation {operation_key} {field} drift: expected {expected}, got {actual}"
   7797         ));
   7798     }
   7799     Ok(())
   7800 }
   7801 
   7802 fn validate_food_availability_operation_sequence(
   7803     operation_key: &str,
   7804     field: &str,
   7805     actual: &[String],
   7806     expected: &[&str],
   7807 ) -> Result<(), String> {
   7808     if !actual
   7809         .iter()
   7810         .map(String::as_str)
   7811         .eq(expected.iter().copied())
   7812     {
   7813         return Err(format!(
   7814             "food availability operation {operation_key} {field} drift: expected {:?}, got {:?}",
   7815             expected, actual
   7816         ));
   7817     }
   7818     Ok(())
   7819 }
   7820 
   7821 fn validate_calendar_operation_authority(
   7822     manifest: &OperationsContractManifest,
   7823     shared_types: &BTreeSet<String>,
   7824 ) -> Result<(), String> {
   7825     for required in REQUIRED_CALENDAR_PUBLIC_TYPES {
   7826         if !shared_types.contains(required) {
   7827             return Err(format!(
   7828                 "calendar operation authority requires shared public type {required}"
   7829             ));
   7830         }
   7831     }
   7832 
   7833     let expected_keys = CALENDAR_OPERATION_EXPECTATIONS
   7834         .iter()
   7835         .map(|expectation| expectation.key.to_string())
   7836         .collect::<BTreeSet<_>>();
   7837     let actual_keys = manifest
   7838         .operations
   7839         .iter()
   7840         .filter(|(key, operation)| {
   7841             key.starts_with("social_calendar_") || operation.id.starts_with("social.calendar")
   7842         })
   7843         .map(|(key, _)| key.clone())
   7844         .collect::<BTreeSet<_>>();
   7845     if actual_keys != expected_keys {
   7846         let missing = expected_keys
   7847             .difference(&actual_keys)
   7848             .cloned()
   7849             .collect::<BTreeSet<_>>();
   7850         let unexpected = actual_keys
   7851             .difference(&expected_keys)
   7852             .cloned()
   7853             .collect::<BTreeSet<_>>();
   7854         return Err(format!(
   7855             "calendar operation authority drift: missing {}; unexpected {}",
   7856             join_set(&missing),
   7857             join_set(&unexpected)
   7858         ));
   7859     }
   7860 
   7861     for expected in CALENDAR_OPERATION_EXPECTATIONS {
   7862         let operation = manifest
   7863             .operations
   7864             .get(expected.key)
   7865             .ok_or_else(|| format!("calendar operation {} is required", expected.key))?;
   7866         validate_calendar_operation_scalar(expected.key, "domain", &operation.domain, "social")?;
   7867         validate_calendar_operation_scalar(expected.key, "id", &operation.id, expected.id)?;
   7868         validate_calendar_operation_scalar(
   7869             expected.key,
   7870             "stability",
   7871             &operation.stability,
   7872             "beta",
   7873         )?;
   7874         validate_calendar_operation_scalar(
   7875             expected.key,
   7876             "error_class",
   7877             &operation.error_class,
   7878             expected.error_class,
   7879         )?;
   7880         validate_calendar_operation_scalar(expected.key, "signing", &operation.signing, "none")?;
   7881         validate_calendar_operation_scalar(
   7882             expected.key,
   7883             "transport",
   7884             &operation.transport,
   7885             "none",
   7886         )?;
   7887         if !operation.deterministic {
   7888             return Err(format!(
   7889                 "calendar operation {} deterministic drift: expected true, got false",
   7890                 expected.key
   7891             ));
   7892         }
   7893         validate_calendar_operation_sequence(
   7894             expected.key,
   7895             "inputs",
   7896             &operation.inputs,
   7897             expected.inputs,
   7898         )?;
   7899         validate_calendar_operation_sequence(
   7900             expected.key,
   7901             "outputs",
   7902             &operation.outputs,
   7903             expected.outputs,
   7904         )?;
   7905         validate_calendar_operation_sequence(
   7906             expected.key,
   7907             "implementation.rust_modules",
   7908             &operation.implementation.rust_modules,
   7909             expected.rust_modules,
   7910         )?;
   7911         validate_calendar_operation_sequence(
   7912             expected.key,
   7913             "implementation.rust_types",
   7914             &operation.implementation.rust_types,
   7915             expected.rust_types,
   7916         )?;
   7917         validate_calendar_operation_scalar(
   7918             expected.key,
   7919             "conformance.vector",
   7920             &operation.conformance.vector,
   7921             expected.vector,
   7922         )?;
   7923     }
   7924 
   7925     Ok(())
   7926 }
   7927 
   7928 fn validate_calendar_operation_scalar(
   7929     operation_key: &str,
   7930     field: &str,
   7931     actual: &str,
   7932     expected: &str,
   7933 ) -> Result<(), String> {
   7934     if actual != expected {
   7935         return Err(format!(
   7936             "calendar operation {operation_key} {field} drift: expected {expected}, got {actual}"
   7937         ));
   7938     }
   7939     Ok(())
   7940 }
   7941 
   7942 fn validate_calendar_operation_sequence(
   7943     operation_key: &str,
   7944     field: &str,
   7945     actual: &[String],
   7946     expected: &[&str],
   7947 ) -> Result<(), String> {
   7948     if !actual
   7949         .iter()
   7950         .map(String::as_str)
   7951         .eq(expected.iter().copied())
   7952     {
   7953         return Err(format!(
   7954             "calendar operation {operation_key} {field} drift: expected {:?}, got {:?}",
   7955             expected, actual
   7956         ));
   7957     }
   7958     Ok(())
   7959 }
   7960 
   7961 fn validate_no_retired_operation_event_names(
   7962     values: &[String],
   7963     context: &str,
   7964 ) -> Result<(), String> {
   7965     for value in values {
   7966         for retired in RETIRED_OPERATION_EVENT_NAMES {
   7967             if value == retired || value.ends_with(&format!("::{retired}")) {
   7968                 return Err(format!(
   7969                     "{context} uses retired event type {retired}; use target-state event and wire names"
   7970                 ));
   7971             }
   7972         }
   7973     }
   7974     Ok(())
   7975 }
   7976 
   7977 fn package_field_configured(table: &toml::value::Table, field: &str) -> bool {
   7978     let Some(value) = table.get(field) else {
   7979         return false;
   7980     };
   7981     match value {
   7982         toml::Value::String(raw) => !raw.trim().is_empty(),
   7983         toml::Value::Array(values) => !values.is_empty(),
   7984         toml::Value::Table(inner) => inner
   7985             .get("workspace")
   7986             .and_then(toml::Value::as_bool)
   7987             .is_some_and(|configured| configured),
   7988         _ => false,
   7989     }
   7990 }
   7991 
   7992 fn package_string_array<'a>(
   7993     package: &'a toml::value::Table,
   7994     crate_name: &str,
   7995     field: &str,
   7996 ) -> Result<Vec<&'a str>, String> {
   7997     let values = package
   7998         .get(field)
   7999         .and_then(toml::Value::as_array)
   8000         .ok_or_else(|| format!("publish crate {crate_name} must define package.{field}"))?;
   8001     if values.is_empty() {
   8002         return Err(format!(
   8003             "publish crate {crate_name} package.{field} must not be empty"
   8004         ));
   8005     }
   8006     let mut resolved = Vec::with_capacity(values.len());
   8007     let mut unique = BTreeSet::new();
   8008     for value in values {
   8009         let value = value.as_str().ok_or_else(|| {
   8010             format!("publish crate {crate_name} package.{field} entries must be strings")
   8011         })?;
   8012         if value.trim().is_empty() {
   8013             return Err(format!(
   8014                 "publish crate {crate_name} package.{field} entries must not be empty"
   8015             ));
   8016         }
   8017         if !unique.insert(value) {
   8018             return Err(format!(
   8019                 "publish crate {crate_name} package.{field} contains duplicate {value}"
   8020             ));
   8021         }
   8022         resolved.push(value);
   8023     }
   8024     Ok(resolved)
   8025 }
   8026 
   8027 fn validate_package_file_matches(
   8028     workspace_root: &Path,
   8029     package_root: &Path,
   8030     crate_name: &str,
   8031     relative: &str,
   8032 ) -> Result<(), String> {
   8033     let package_path = package_root.join(relative);
   8034     let root_path = workspace_root.join(relative);
   8035     let package_bytes = fs::read(&package_path)
   8036         .map_err(|error| format!("publish crate {crate_name} must include {relative}: {error}"))?;
   8037     let root_bytes =
   8038         fs::read(&root_path).map_err(|error| format!("read {}: {error}", root_path.display()))?;
   8039     if package_bytes != root_bytes {
   8040         return Err(format!(
   8041             "publish crate {crate_name} {relative} must match the workspace license"
   8042         ));
   8043     }
   8044     Ok(())
   8045 }
   8046 
   8047 fn validate_publish_package_metadata(
   8048     workspace_root: &Path,
   8049     publish_crates: &BTreeSet<String>,
   8050 ) -> Result<(), String> {
   8051     let mut package_records = BTreeMap::new();
   8052     for record in workspace_package_records(workspace_root)? {
   8053         if package_records
   8054             .insert(record.name.clone(), record)
   8055             .is_some()
   8056         {
   8057             return Err("duplicate workspace package name in package metadata map".to_string());
   8058         }
   8059     }
   8060     for crate_name in publish_crates {
   8061         let record = match package_records.get(crate_name) {
   8062             Some(record) => record,
   8063             None => {
   8064                 return Err(format!(
   8065                     "publish crate {} has no workspace manifest",
   8066                     crate_name
   8067                 ));
   8068             }
   8069         };
   8070         let package = record
   8071             .manifest_value
   8072             .get("package")
   8073             .and_then(toml::Value::as_table)
   8074             .expect("workspace package records include [package] table");
   8075 
   8076         if !package_field_configured(package, "description") {
   8077             return Err(format!(
   8078                 "publish crate {} must define a non-empty package.description",
   8079                 crate_name
   8080             ));
   8081         }
   8082         for field in [
   8083             "authors",
   8084             "version",
   8085             "edition",
   8086             "rust-version",
   8087             "license",
   8088             "repository",
   8089             "homepage",
   8090             "documentation",
   8091             "readme",
   8092         ] {
   8093             if !package_field_configured(package, field) {
   8094                 return Err(format!(
   8095                     "publish crate {} must configure package.{}",
   8096                     crate_name, field
   8097                 ));
   8098             }
   8099         }
   8100 
   8101         let expected_documentation = format!("https://docs.rs/{crate_name}");
   8102         if package.get("documentation").and_then(toml::Value::as_str)
   8103             != Some(expected_documentation.as_str())
   8104         {
   8105             return Err(format!(
   8106                 "publish crate {crate_name} package.documentation must be {expected_documentation}"
   8107             ));
   8108         }
   8109         if package.get("license-file").is_some() {
   8110             return Err(format!(
   8111                 "publish crate {crate_name} must use the workspace SPDX license expression"
   8112             ));
   8113         }
   8114 
   8115         let keywords = package_string_array(package, crate_name, "keywords")?;
   8116         if keywords.len() > 5 {
   8117             return Err(format!(
   8118                 "publish crate {crate_name} package.keywords exceeds the crates.io limit of 5"
   8119             ));
   8120         }
   8121         let categories = package_string_array(package, crate_name, "categories")?;
   8122         if categories.len() > 5 {
   8123             return Err(format!(
   8124                 "publish crate {crate_name} package.categories exceeds the crates.io limit of 5"
   8125             ));
   8126         }
   8127 
   8128         let include = package_string_array(package, crate_name, "include")?;
   8129         for required in [
   8130             "src/**",
   8131             "tests/**",
   8132             "README.md",
   8133             "LICENSE-APACHE",
   8134             "LICENSE-MIT",
   8135         ] {
   8136             if !include.contains(&required) {
   8137                 return Err(format!(
   8138                     "publish crate {crate_name} package.include must contain {required}"
   8139                 ));
   8140             }
   8141         }
   8142 
   8143         let package_root = record
   8144             .manifest_path
   8145             .parent()
   8146             .expect("workspace member manifest has a parent");
   8147         if !package_root.join("README.md").is_file() {
   8148             return Err(format!(
   8149                 "publish crate {crate_name} must include a package-local README.md"
   8150             ));
   8151         }
   8152         validate_package_file_matches(workspace_root, package_root, crate_name, "LICENSE-APACHE")?;
   8153         validate_package_file_matches(workspace_root, package_root, crate_name, "LICENSE-MIT")?;
   8154 
   8155         let docs_rs = package
   8156             .get("metadata")
   8157             .and_then(toml::Value::as_table)
   8158             .and_then(|metadata| metadata.get("docs"))
   8159             .and_then(toml::Value::as_table)
   8160             .and_then(|docs| docs.get("rs"))
   8161             .and_then(toml::Value::as_table)
   8162             .ok_or_else(|| {
   8163                 format!("publish crate {crate_name} must define [package.metadata.docs.rs]")
   8164             })?;
   8165         if docs_rs
   8166             .get("all-features")
   8167             .and_then(toml::Value::as_bool)
   8168             .unwrap_or(false)
   8169         {
   8170             return Err(format!(
   8171                 "publish crate {crate_name} docs.rs must use an intentional feature set"
   8172             ));
   8173         }
   8174         let docs_features = docs_rs
   8175             .get("features")
   8176             .and_then(toml::Value::as_array)
   8177             .ok_or_else(|| format!("publish crate {crate_name} docs.rs must define features"))?;
   8178         let declared_features = record
   8179             .manifest_value
   8180             .get("features")
   8181             .and_then(toml::Value::as_table);
   8182         for feature in docs_features {
   8183             let feature = feature.as_str().ok_or_else(|| {
   8184                 format!("publish crate {crate_name} docs.rs features must be strings")
   8185             })?;
   8186             if !declared_features.is_some_and(|features| features.contains_key(feature)) {
   8187                 return Err(format!(
   8188                     "publish crate {crate_name} docs.rs selects unknown feature {feature}"
   8189                 ));
   8190             }
   8191         }
   8192     }
   8193     Ok(())
   8194 }
   8195 
   8196 fn parse_coverage_percent(raw: &str, field: &str, crate_name: &str) -> Result<f64, String> {
   8197     match raw.parse::<f64>() {
   8198         Ok(value) => Ok(value),
   8199         Err(e) => Err(format!("parse {} for {}: {e}", field, crate_name)),
   8200     }
   8201 }
   8202 
   8203 fn parse_branch_coverage_percent(raw: &str, crate_name: &str) -> Result<Option<f64>, String> {
   8204     if raw == "unavailable" {
   8205         return Ok(None);
   8206     }
   8207     parse_coverage_percent(raw, "branch", crate_name).map(Some)
   8208 }
   8209 
   8210 fn branch_coverage_fails(branch: Option<f64>, thresholds: CoverageThresholds) -> bool {
   8211     match branch {
   8212         Some(value) => value < thresholds.fail_under_branches,
   8213         None => thresholds.require_branches,
   8214     }
   8215 }
   8216 
   8217 fn branch_coverage_display(branch: Option<f64>) -> String {
   8218     branch
   8219         .map(|value| value.to_string())
   8220         .unwrap_or_else(|| "unavailable".to_string())
   8221 }
   8222 
   8223 #[derive(Debug)]
   8224 struct CoverageRefreshRow {
   8225     status: String,
   8226     exec: f64,
   8227     func: f64,
   8228     branch: Option<f64>,
   8229     region: f64,
   8230     report_path: PathBuf,
   8231 }
   8232 
   8233 #[derive(Debug, Deserialize)]
   8234 struct CoverageGateReportForValidation {
   8235     scope: String,
   8236     thresholds: CoverageGateReportThresholdsForValidation,
   8237     measured: CoverageGateReportMeasuredForValidation,
   8238     result: CoverageGateReportResultForValidation,
   8239 }
   8240 
   8241 #[derive(Debug, Deserialize)]
   8242 struct CoverageGateReportThresholdsForValidation {
   8243     executable_lines: f64,
   8244     functions: f64,
   8245     regions: f64,
   8246     branches: f64,
   8247     branches_required: bool,
   8248 }
   8249 
   8250 #[derive(Debug, Deserialize)]
   8251 struct CoverageGateReportMeasuredForValidation {
   8252     executable_lines_percent: f64,
   8253     functions_percent: f64,
   8254     branches_percent: Option<f64>,
   8255     branches_available: bool,
   8256     summary_regions_percent: f64,
   8257 }
   8258 
   8259 #[derive(Debug, Deserialize)]
   8260 struct CoverageGateReportResultForValidation {
   8261     pass: bool,
   8262 }
   8263 
   8264 type CoverageRefreshRows = BTreeMap<String, CoverageRefreshRow>;
   8265 
   8266 fn coverage_refresh_report_path(
   8267     workspace_root: &Path,
   8268     report_path: &Path,
   8269     raw_report_path: &str,
   8270     crate_name: &str,
   8271 ) -> Result<PathBuf, String> {
   8272     let trimmed = raw_report_path.trim();
   8273     if trimmed.is_empty() {
   8274         return Err(format!(
   8275             "coverage row for crate {} in {} must include a report path",
   8276             crate_name,
   8277             report_path.display()
   8278         ));
   8279     }
   8280     let path = Path::new(trimmed);
   8281     if path.is_absolute() {
   8282         Ok(path.to_path_buf())
   8283     } else {
   8284         Ok(workspace_root.join(path))
   8285     }
   8286 }
   8287 
   8288 fn load_coverage_refresh_rows(workspace_root: &Path) -> Result<CoverageRefreshRows, String> {
   8289     let report_path = workspace_root
   8290         .join("target")
   8291         .join("coverage")
   8292         .join("coverage-refresh.tsv");
   8293     let raw = match fs::read_to_string(&report_path) {
   8294         Ok(raw) => raw,
   8295         Err(e) => return Err(format!("read {}: {e}", report_path.display())),
   8296     };
   8297     let mut rows = BTreeMap::new();
   8298     for line in raw.lines().skip(1) {
   8299         let trimmed = line.trim();
   8300         if trimmed.is_empty() {
   8301             continue;
   8302         }
   8303         let parts = trimmed.split('\t').collect::<Vec<_>>();
   8304         if parts.len() < 7 {
   8305             return Err(format!(
   8306                 "coverage row must have at least 7 columns in {}: {}",
   8307                 report_path.display(),
   8308                 trimmed
   8309             ));
   8310         }
   8311         let crate_name = parts[0].to_string();
   8312         let status = parts[1].to_string();
   8313         let exec = parse_coverage_percent(parts[2], "exec", &crate_name)?;
   8314         let func = parse_coverage_percent(parts[3], "func", &crate_name)?;
   8315         let branch = parse_branch_coverage_percent(parts[4], &crate_name)?;
   8316         let region = parse_coverage_percent(parts[5], "region", &crate_name)?;
   8317         let row_report_path =
   8318             coverage_refresh_report_path(workspace_root, &report_path, parts[6], &crate_name)?;
   8319         if rows
   8320             .insert(
   8321                 crate_name.clone(),
   8322                 CoverageRefreshRow {
   8323                     status,
   8324                     exec,
   8325                     func,
   8326                     branch,
   8327                     region,
   8328                     report_path: row_report_path,
   8329                 },
   8330             )
   8331             .is_some()
   8332         {
   8333             return Err(format!(
   8334                 "duplicate coverage row for crate {} in {}",
   8335                 crate_name,
   8336                 report_path.display()
   8337             ));
   8338         }
   8339     }
   8340     Ok(rows)
   8341 }
   8342 
   8343 #[cfg_attr(not(test), allow(dead_code))]
   8344 fn validate_required_coverage_summary(
   8345     workspace_root: &Path,
   8346     required_crates: &BTreeSet<String>,
   8347     thresholds: CoverageThresholds,
   8348 ) -> Result<(), String> {
   8349     let rows = load_coverage_refresh_rows(workspace_root)?;
   8350     for crate_name in required_crates {
   8351         let row = rows.get(crate_name).ok_or_else(|| {
   8352             format!(
   8353                 "required coverage crate {} missing from coverage-refresh.tsv",
   8354                 crate_name
   8355             )
   8356         })?;
   8357         if row.status != "pass" {
   8358             return Err(format!(
   8359                 "required coverage crate {} has non-pass status {}",
   8360                 crate_name, row.status
   8361             ));
   8362         }
   8363         if row.exec < thresholds.fail_under_exec_lines
   8364             || row.func < thresholds.fail_under_functions
   8365             || branch_coverage_fails(row.branch, thresholds)
   8366             || row.region < thresholds.fail_under_regions
   8367         {
   8368             return Err(format!(
   8369                 "required coverage crate {} must satisfy coverage policy {},{},{},{}, found {}/{}/{}/{}",
   8370                 crate_name,
   8371                 thresholds.fail_under_exec_lines,
   8372                 thresholds.fail_under_functions,
   8373                 thresholds.fail_under_branches,
   8374                 thresholds.fail_under_regions,
   8375                 row.exec,
   8376                 row.func,
   8377                 branch_coverage_display(row.branch),
   8378                 row.region
   8379             ));
   8380         }
   8381     }
   8382     Ok(())
   8383 }
   8384 
   8385 fn read_coverage_gate_report(
   8386     path: &Path,
   8387     crate_name: &str,
   8388 ) -> Result<CoverageGateReportForValidation, String> {
   8389     let raw = match fs::read_to_string(path) {
   8390         Ok(raw) => raw,
   8391         Err(e) => {
   8392             return Err(format!(
   8393                 "read coverage gate report for {} at {}: {e}",
   8394                 crate_name,
   8395                 path.display()
   8396             ));
   8397         }
   8398     };
   8399     serde_json::from_str::<CoverageGateReportForValidation>(&raw).map_err(|e| {
   8400         format!(
   8401             "parse coverage gate report for {} at {}: {e}",
   8402             crate_name,
   8403             path.display()
   8404         )
   8405     })
   8406 }
   8407 
   8408 fn coverage_percent_matches(left: f64, right: f64) -> bool {
   8409     (left - right).abs() <= COVERAGE_REPORT_EPSILON
   8410 }
   8411 
   8412 fn coverage_branch_percent_matches(left: Option<f64>, right: Option<f64>) -> bool {
   8413     match (left, right) {
   8414         (Some(left), Some(right)) => coverage_percent_matches(left, right),
   8415         (None, None) => true,
   8416         _ => false,
   8417     }
   8418 }
   8419 
   8420 fn coverage_gate_report_thresholds_match(
   8421     report: &CoverageGateReportThresholdsForValidation,
   8422     thresholds: CoverageThresholds,
   8423 ) -> bool {
   8424     coverage_percent_matches(report.executable_lines, thresholds.fail_under_exec_lines)
   8425         && coverage_percent_matches(report.functions, thresholds.fail_under_functions)
   8426         && coverage_percent_matches(report.regions, thresholds.fail_under_regions)
   8427         && coverage_percent_matches(report.branches, thresholds.fail_under_branches)
   8428         && report.branches_required == thresholds.require_branches
   8429 }
   8430 
   8431 fn validate_coverage_gate_report_for_row(
   8432     crate_name: &str,
   8433     row: &CoverageRefreshRow,
   8434     thresholds: CoverageThresholds,
   8435 ) -> Result<(), String> {
   8436     let report = read_coverage_gate_report(&row.report_path, crate_name)?;
   8437     if report.scope != crate_name {
   8438         return Err(format!(
   8439             "coverage gate report {} has scope {}, expected {}",
   8440             row.report_path.display(),
   8441             report.scope,
   8442             crate_name
   8443         ));
   8444     }
   8445     if !coverage_gate_report_thresholds_match(&report.thresholds, thresholds) {
   8446         return Err(format!(
   8447             "coverage gate report {} for {} thresholds do not match policy",
   8448             row.report_path.display(),
   8449             crate_name
   8450         ));
   8451     }
   8452     if !report.result.pass {
   8453         return Err(format!(
   8454             "coverage gate report {} for {} has non-pass result",
   8455             row.report_path.display(),
   8456             crate_name
   8457         ));
   8458     }
   8459     if report.measured.branches_available != report.measured.branches_percent.is_some() {
   8460         return Err(format!(
   8461             "coverage gate report {} for {} has inconsistent branch measurement",
   8462             row.report_path.display(),
   8463             crate_name
   8464         ));
   8465     }
   8466     if !coverage_percent_matches(row.exec, report.measured.executable_lines_percent)
   8467         || !coverage_percent_matches(row.func, report.measured.functions_percent)
   8468         || !coverage_branch_percent_matches(row.branch, report.measured.branches_percent)
   8469         || !coverage_percent_matches(row.region, report.measured.summary_regions_percent)
   8470     {
   8471         return Err(format!(
   8472             "coverage row for {} does not match coverage gate report {}",
   8473             crate_name,
   8474             row.report_path.display()
   8475         ));
   8476     }
   8477     Ok(())
   8478 }
   8479 
   8480 fn validate_required_coverage_summary_with_policy(
   8481     workspace_root: &Path,
   8482     required_crates: &BTreeSet<String>,
   8483     policy: &CoveragePolicyFile,
   8484 ) -> Result<(), String> {
   8485     let rows = load_coverage_refresh_rows(workspace_root)?;
   8486     for crate_name in required_crates {
   8487         let row = rows.get(crate_name).ok_or_else(|| {
   8488             format!(
   8489                 "required coverage crate {} missing from coverage-refresh.tsv",
   8490                 crate_name
   8491             )
   8492         })?;
   8493         if row.status != "pass" {
   8494             return Err(format!(
   8495                 "required coverage crate {} has non-pass status {}",
   8496                 crate_name, row.status
   8497             ));
   8498         }
   8499         let thresholds = policy.thresholds_for_scope(crate_name);
   8500         validate_coverage_gate_report_for_row(crate_name, row, thresholds)?;
   8501         if row.exec < thresholds.fail_under_exec_lines
   8502             || row.func < thresholds.fail_under_functions
   8503             || branch_coverage_fails(row.branch, thresholds)
   8504             || row.region < thresholds.fail_under_regions
   8505         {
   8506             return Err(format!(
   8507                 "required coverage crate {} must satisfy coverage policy {},{},{},{}, found {}/{}/{}/{}",
   8508                 crate_name,
   8509                 thresholds.fail_under_exec_lines,
   8510                 thresholds.fail_under_functions,
   8511                 thresholds.fail_under_branches,
   8512                 thresholds.fail_under_regions,
   8513                 row.exec,
   8514                 row.func,
   8515                 branch_coverage_display(row.branch),
   8516                 row.region
   8517             ));
   8518         }
   8519     }
   8520     Ok(())
   8521 }
   8522 
   8523 const CORE_UNIT_DIMENSION_ENUM: &str = "UnitDimension";
   8524 const CORE_UNIT_DIMENSION_ORDER: [&str; 3] = ["Count", "Mass", "Volume"];
   8525 
   8526 fn extract_enum_body<'a>(source: &'a str, enum_name: &str) -> Result<&'a str, String> {
   8527     let marker = format!("pub enum {enum_name}");
   8528     let enum_start = match source.find(&marker) {
   8529         Some(index) => index,
   8530         None => return Err(format!("missing enum {enum_name}")),
   8531     };
   8532     let after_start = &source[enum_start..];
   8533     let open_rel = match after_start.find('{') {
   8534         Some(index) => index,
   8535         None => return Err(format!("missing opening brace for enum {enum_name}")),
   8536     };
   8537     let open_idx = enum_start + open_rel;
   8538     let mut depth = 0usize;
   8539     for (offset, ch) in source[open_idx..].char_indices() {
   8540         if ch == '{' {
   8541             depth += 1;
   8542             continue;
   8543         }
   8544         if ch != '}' {
   8545             continue;
   8546         }
   8547         depth = depth.saturating_sub(1);
   8548         if depth == 0 {
   8549             let close_idx = open_idx + offset;
   8550             return Ok(&source[(open_idx + 1)..close_idx]);
   8551         }
   8552     }
   8553     Err(format!("missing closing brace for enum {enum_name}"))
   8554 }
   8555 
   8556 fn parse_enum_variants(enum_body: &str) -> Vec<String> {
   8557     enum_body
   8558         .lines()
   8559         .filter_map(|line| {
   8560             let trimmed = line.trim();
   8561             if trimmed.is_empty() || trimmed.starts_with('#') || trimmed.starts_with("//") {
   8562                 return None;
   8563             }
   8564             let before_comma = trimmed
   8565                 .split_once(',')
   8566                 .map_or(trimmed, |(head, _)| head)
   8567                 .trim();
   8568             if before_comma.is_empty() {
   8569                 return None;
   8570             }
   8571             let before_discriminant = before_comma
   8572                 .split_once('=')
   8573                 .map_or(before_comma, |(head, _)| head)
   8574                 .trim();
   8575             if before_discriminant.is_empty() {
   8576                 return None;
   8577             }
   8578             let ident = before_discriminant
   8579                 .split_whitespace()
   8580                 .next()
   8581                 .unwrap_or_default();
   8582             Some(ident.to_string())
   8583         })
   8584         .collect()
   8585 }
   8586 
   8587 fn validate_core_unit_dimension_variant_order(workspace_root: &Path) -> Result<(), String> {
   8588     let source_path = workspace_root
   8589         .join("crates")
   8590         .join("core")
   8591         .join("src")
   8592         .join("unit.rs");
   8593     let source = match fs::read_to_string(&source_path) {
   8594         Ok(source) => source,
   8595         Err(e) => return Err(format!("read {}: {e}", source_path.display())),
   8596     };
   8597     let enum_body = extract_enum_body(&source, CORE_UNIT_DIMENSION_ENUM)?;
   8598     let variants = parse_enum_variants(enum_body);
   8599     let expected = CORE_UNIT_DIMENSION_ORDER
   8600         .iter()
   8601         .map(|item| (*item).to_string())
   8602         .collect::<Vec<_>>();
   8603     if variants != expected {
   8604         return Err(format!(
   8605             "core unit dimension variant order must be {} but was {}",
   8606             CORE_UNIT_DIMENSION_ORDER.join(", "),
   8607             variants.join(", ")
   8608         ));
   8609     }
   8610     Ok(())
   8611 }
   8612 
   8613 fn validate_coverage_policy_parity(
   8614     workspace_root: &Path,
   8615     contract_root: &Path,
   8616 ) -> Result<(), String> {
   8617     let policy = load_coverage_policy(contract_root)?;
   8618     let thresholds = policy.thresholds();
   8619     if thresholds.fail_under_exec_lines != COVERAGE_REQUIRED_THRESHOLD
   8620         || thresholds.fail_under_functions != COVERAGE_REQUIRED_THRESHOLD
   8621         || thresholds.fail_under_regions != COVERAGE_REQUIRED_THRESHOLD
   8622         || thresholds.fail_under_branches != COVERAGE_REQUIRED_THRESHOLD
   8623         || !thresholds.require_branches
   8624     {
   8625         return Err(format!(
   8626             "coverage policy must enforce {COVERAGE_REQUIRED_THRESHOLD_LABEL} with required branches"
   8627         ));
   8628     }
   8629 
   8630     let required_packages = policy
   8631         .required_crate_entries()
   8632         .iter()
   8633         .cloned()
   8634         .collect::<BTreeSet<_>>();
   8635     for package in &required_packages {
   8636         let scoped = policy.thresholds_for_scope(package);
   8637         if scoped.fail_under_exec_lines < COVERAGE_REQUIRED_THRESHOLD
   8638             || scoped.fail_under_functions < COVERAGE_REQUIRED_THRESHOLD
   8639             || scoped.fail_under_regions < COVERAGE_REQUIRED_THRESHOLD
   8640             || scoped.fail_under_branches < COVERAGE_REQUIRED_THRESHOLD
   8641         {
   8642             return Err(format!(
   8643                 "coverage policy scope {package} must enforce at least {COVERAGE_REQUIRED_THRESHOLD_LABEL}"
   8644             ));
   8645         }
   8646     }
   8647     let expected_packages = coverage_required_workspace_crates(workspace_root)?;
   8648     if expected_packages != required_packages {
   8649         let missing = expected_packages
   8650             .difference(&required_packages)
   8651             .cloned()
   8652             .collect::<BTreeSet<_>>();
   8653         let extra = required_packages
   8654             .difference(&expected_packages)
   8655             .cloned()
   8656             .collect::<BTreeSet<_>>();
   8657         return Err(format!(
   8658             "coverage policy missing workspace crates: {}; coverage policy includes excluded or unknown crates: {}",
   8659             join_set(&missing),
   8660             join_set(&extra)
   8661         ));
   8662     }
   8663 
   8664     Ok(())
   8665 }
   8666 
   8667 fn publish_config_is_public(publish: Option<&PackagePublish>) -> bool {
   8668     matches!(
   8669         publish,
   8670         Some(PackagePublish::Registries(registries))
   8671             if registries.len() == 1 && registries[0] == "crates-io"
   8672     )
   8673 }
   8674 
   8675 fn publish_config_is_non_public(publish: Option<&PackagePublish>) -> bool {
   8676     matches!(publish, Some(PackagePublish::Bool(false)))
   8677 }
   8678 
   8679 fn validate_publication_control(
   8680     release: &ReleaseContractFile,
   8681     publish_configs: &BTreeMap<String, Option<PackagePublish>>,
   8682     require_control: bool,
   8683 ) -> Result<bool, String> {
   8684     let Some(control) = release.publication.as_ref() else {
   8685         if require_control {
   8686             return Err("publication control is required".to_string());
   8687         }
   8688         return Ok(false);
   8689     };
   8690     if control.registry != "crates-io" {
   8691         return Err("publication.registry must be crates-io".to_string());
   8692     }
   8693     if control.final_enablement_step != 305 {
   8694         return Err("publication.final_enablement_step must be 305".to_string());
   8695     }
   8696     if !control.frozen {
   8697         return Ok(false);
   8698     }
   8699     for (crate_name, publish) in publish_configs {
   8700         if !publish_config_is_non_public(publish.as_ref()) {
   8701             return Err(format!(
   8702                 "publication freeze requires workspace crate {} to set publish = false",
   8703                 crate_name
   8704             ));
   8705         }
   8706     }
   8707     Ok(true)
   8708 }
   8709 
   8710 fn validate_v1_release_policy(
   8711     workspace_root: &Path,
   8712     release: &ReleaseContractFile,
   8713     workspace_packages: &BTreeSet<String>,
   8714     publish_configs: &BTreeMap<String, Option<PackagePublish>>,
   8715     require_v1: bool,
   8716 ) -> Result<Option<BTreeSet<String>>, String> {
   8717     let Some(control) = release.publication.as_ref() else {
   8718         if require_v1 {
   8719             return Err("publication control is required".to_string());
   8720         }
   8721         return Ok(None);
   8722     };
   8723     let declares_v1 = !control.spec_id.is_empty()
   8724         || !control.approved_packages.is_empty()
   8725         || !control.local_packages.is_empty()
   8726         || !control.external_packages.is_empty()
   8727         || release.workspace_classification.is_some();
   8728     if !declares_v1 {
   8729         if require_v1 {
   8730             return Err("publication must define the v1 approved package authority".to_string());
   8731         }
   8732         return Ok(None);
   8733     }
   8734 
   8735     let architecture_path =
   8736         workspace_root.join("contracts/crates/release_v1/radroots_crates_release_v1.toml");
   8737     let architecture = parse_toml::<CratesReleaseArchitecture>(&architecture_path)?;
   8738     let expected_approved = collect_unique_set(
   8739         &architecture
   8740             .package
   8741             .iter()
   8742             .map(|package| package.name.clone())
   8743             .collect::<Vec<_>>(),
   8744         "architecture.package.name",
   8745     )?;
   8746     if architecture.package_count != expected_approved.len() || architecture.package_count != 19 {
   8747         return Err(format!(
   8748             "release architecture must define exactly 19 unique packages, found package_count {} and {} unique package records",
   8749             architecture.package_count,
   8750             expected_approved.len()
   8751         ));
   8752     }
   8753     if control.spec_id != architecture.spec_id || control.spec_id != "radroots.crates.release.v1" {
   8754         return Err(format!(
   8755             "publication.spec_id {} must match architecture id {}",
   8756             control.spec_id, architecture.spec_id
   8757         ));
   8758     }
   8759 
   8760     let approved = collect_unique_set(&control.approved_packages, "publication.approved_packages")?;
   8761     let local = collect_unique_set(&control.local_packages, "publication.local_packages")?;
   8762     let external = collect_unique_set(&control.external_packages, "publication.external_packages")?;
   8763     let legacy_local = collect_unique_set(
   8764         &architecture.repositories.lib.packages,
   8765         "architecture.repositories.lib.packages",
   8766     )?;
   8767     let legacy_external = collect_unique_set(
   8768         &architecture.repositories.sdk.packages,
   8769         "architecture.repositories.sdk.packages",
   8770     )?;
   8771     let consolidation_path = workspace_root.join("contracts/consolidation/architecture.v1.toml");
   8772     let workspace =
   8773         parse_toml::<WorkspaceVersionCargoManifest>(&workspace_root.join("Cargo.toml"))?;
   8774     let consolidated_here = if consolidation_path.is_file() {
   8775         let consolidation = parse_toml::<ConsolidationReleaseOwnership>(&consolidation_path)?;
   8776         workspace.workspace.package.repository == consolidation.canonical_rust_repository
   8777     } else {
   8778         false
   8779     };
   8780     let (expected_local, expected_external) = if consolidated_here {
   8781         (expected_approved.clone(), BTreeSet::new())
   8782     } else {
   8783         (legacy_local, legacy_external)
   8784     };
   8785     for (field, actual, expected) in [
   8786         (
   8787             "publication.approved_packages",
   8788             &approved,
   8789             &expected_approved,
   8790         ),
   8791         ("publication.local_packages", &local, &expected_local),
   8792         (
   8793             "publication.external_packages",
   8794             &external,
   8795             &expected_external,
   8796         ),
   8797     ] {
   8798         if actual != expected {
   8799             let missing = expected
   8800                 .difference(actual)
   8801                 .cloned()
   8802                 .collect::<BTreeSet<_>>();
   8803             let extra = actual
   8804                 .difference(expected)
   8805                 .cloned()
   8806                 .collect::<BTreeSet<_>>();
   8807             return Err(format!(
   8808                 "{field} is missing approved packages: {}; {field} has unapproved packages: {}",
   8809                 join_set(&missing),
   8810                 join_set(&extra)
   8811             ));
   8812         }
   8813     }
   8814     let ownership_overlap = local
   8815         .intersection(&external)
   8816         .cloned()
   8817         .collect::<BTreeSet<_>>();
   8818     if !ownership_overlap.is_empty() {
   8819         return Err(format!(
   8820             "local and external approved package ownership overlaps: {}",
   8821             join_set(&ownership_overlap)
   8822         ));
   8823     }
   8824     let mut owned = local.clone();
   8825     owned.extend(external.iter().cloned());
   8826     if owned != approved {
   8827         return Err(
   8828             "local and external package ownership must partition approved packages".to_string(),
   8829         );
   8830     }
   8831     let external_in_workspace = external
   8832         .intersection(workspace_packages)
   8833         .cloned()
   8834         .collect::<BTreeSet<_>>();
   8835     if !external_in_workspace.is_empty() {
   8836         return Err(format!(
   8837             "externally owned approved packages must not be workspace members: {}",
   8838             join_set(&external_in_workspace)
   8839         ));
   8840     }
   8841 
   8842     let classification = release.workspace_classification.as_ref().ok_or_else(|| {
   8843         "workspace_classification is required for the v1 release policy".to_string()
   8844     })?;
   8845     let private = collect_unique_set(&classification.private, "workspace_classification.private")?;
   8846     let build_codegen = collect_unique_set(
   8847         &classification.build_codegen,
   8848         "workspace_classification.build_codegen",
   8849     )?;
   8850     let test_support = collect_unique_set(
   8851         &classification.test_support,
   8852         "workspace_classification.test_support",
   8853     )?;
   8854     let preview = collect_unique_set(&classification.preview, "workspace_classification.preview")?;
   8855     let retired = collect_unique_set(&classification.retired, "workspace_classification.retired")?;
   8856     let classes = [
   8857         ("private", &private),
   8858         ("build-codegen", &build_codegen),
   8859         ("test-support", &test_support),
   8860         ("preview", &preview),
   8861         ("retired", &retired),
   8862     ];
   8863     for index in 0..classes.len() {
   8864         for other_index in (index + 1)..classes.len() {
   8865             let overlap = classes[index]
   8866                 .1
   8867                 .intersection(classes[other_index].1)
   8868                 .cloned()
   8869                 .collect::<BTreeSet<_>>();
   8870             if !overlap.is_empty() {
   8871                 return Err(format!(
   8872                     "workspace classification overlap is not allowed between {} and {}: {}",
   8873                     classes[index].0,
   8874                     classes[other_index].0,
   8875                     join_set(&overlap)
   8876                 ));
   8877             }
   8878         }
   8879     }
   8880     let mut classified = BTreeSet::new();
   8881     for (_, entries) in classes {
   8882         classified.extend(entries.iter().cloned());
   8883     }
   8884     let local_workspace_packages = local
   8885         .intersection(workspace_packages)
   8886         .cloned()
   8887         .collect::<BTreeSet<_>>();
   8888     let public_classification_overlap = classified
   8889         .intersection(&local_workspace_packages)
   8890         .cloned()
   8891         .collect::<BTreeSet<_>>();
   8892     if !public_classification_overlap.is_empty() {
   8893         return Err(format!(
   8894             "approved local packages must not be classified as private workspace packages: {}",
   8895             join_set(&public_classification_overlap)
   8896         ));
   8897     }
   8898     let mut accounted = classified.clone();
   8899     accounted.extend(local_workspace_packages.iter().cloned());
   8900     if accounted != *workspace_packages {
   8901         let missing = workspace_packages
   8902             .difference(&accounted)
   8903             .cloned()
   8904             .collect::<BTreeSet<_>>();
   8905         let extra = accounted
   8906             .difference(workspace_packages)
   8907             .cloned()
   8908             .collect::<BTreeSet<_>>();
   8909         return Err(format!(
   8910             "workspace classification is missing packages: {}; workspace classification has unknown packages: {}",
   8911             join_set(&missing),
   8912             join_set(&extra)
   8913         ));
   8914     }
   8915 
   8916     if control.registry != "crates-io" {
   8917         return Err("publication.registry must be crates-io".to_string());
   8918     }
   8919     if control.final_enablement_step != 305 {
   8920         return Err("publication.final_enablement_step must be 305".to_string());
   8921     }
   8922     let publish_order = collect_unique_set(&release.publish_order.crates, "publish_order.crates")?;
   8923     if control.frozen {
   8924         if !publish_order.is_empty() {
   8925             return Err(
   8926                 "publish_order.crates must remain empty while publication is frozen".to_string(),
   8927             );
   8928         }
   8929         for (crate_name, publish) in publish_configs {
   8930             if !publish_config_is_non_public(publish.as_ref()) {
   8931                 return Err(format!(
   8932                     "publication freeze requires workspace crate {} to set publish = false",
   8933                     crate_name
   8934                 ));
   8935             }
   8936         }
   8937         return Ok(Some(BTreeSet::new()));
   8938     }
   8939 
   8940     if local_workspace_packages != local {
   8941         let missing = local
   8942             .difference(&local_workspace_packages)
   8943             .cloned()
   8944             .collect::<BTreeSet<_>>();
   8945         return Err(format!(
   8946             "publication enablement is missing approved local workspace packages: {}",
   8947             join_set(&missing)
   8948         ));
   8949     }
   8950     if publish_order != local {
   8951         return Err("publish_order.crates must contain exactly the approved local packages when publication is enabled".to_string());
   8952     }
   8953     for (crate_name, publish) in publish_configs {
   8954         if local.contains(crate_name) {
   8955             if !publish_config_is_public(publish.as_ref()) {
   8956                 return Err(format!(
   8957                     "approved local crate {} must set publish = [\"crates-io\"]",
   8958                     crate_name
   8959                 ));
   8960             }
   8961         } else if !publish_config_is_non_public(publish.as_ref()) {
   8962             return Err(format!(
   8963                 "private workspace crate {} must set publish = false",
   8964                 crate_name
   8965             ));
   8966         }
   8967     }
   8968     Ok(Some(local))
   8969 }
   8970 
   8971 #[cfg(test)]
   8972 fn validate_release_publish_policy(
   8973     workspace_root: &Path,
   8974     _contract_root: &Path,
   8975     contract_version: &str,
   8976 ) -> Result<(), String> {
   8977     let release = load_release_contract(workspace_root, contract_version)?;
   8978     if release.release.version.trim().is_empty() {
   8979         return Err("release.version must not be empty".to_string());
   8980     }
   8981     if release.release.version != contract_version {
   8982         return Err(format!(
   8983             "release.version {} must match contract version {}",
   8984             release.release.version, contract_version
   8985         ));
   8986     }
   8987 
   8988     let workspace_packages = workspace_package_names(workspace_root)?
   8989         .into_iter()
   8990         .collect::<BTreeSet<_>>();
   8991     let publish_configs = workspace_package_publish_configs(workspace_root)
   8992         .expect("workspace publish configs are stable");
   8993     if validate_v1_release_policy(
   8994         workspace_root,
   8995         &release,
   8996         &workspace_packages,
   8997         &publish_configs,
   8998         false,
   8999     )?
   9000     .is_some()
   9001     {
   9002         return Ok(());
   9003     }
   9004     let uses_classification = release.uses_classification();
   9005     let public_field = if uses_classification {
   9006         "classification.public"
   9007     } else {
   9008         "publish.crates"
   9009     };
   9010     let internal_field = if uses_classification {
   9011         "classification.internal"
   9012     } else {
   9013         "internal.crates"
   9014     };
   9015 
   9016     let public_set = collect_unique_set(&release.public_crates(), public_field)?;
   9017     let internal_set = collect_unique_set(&release.internal_crates(), internal_field)?;
   9018     let deferred_set = collect_unique_set(&release.deferred_crates(), "classification.deferred")?;
   9019     let retired_set = collect_unique_set(&release.retired_crates(), "classification.retired")?;
   9020     let yank_only_set =
   9021         collect_unique_set(&release.yank_only_crates(), "classification.yank_only")?;
   9022     let publish_order = &release.publish_order.crates;
   9023     let publish_order_set = collect_unique_set(publish_order, "publish_order.crates")?;
   9024 
   9025     let class_sets = [
   9026         ("public", &public_set),
   9027         ("internal", &internal_set),
   9028         ("deferred", &deferred_set),
   9029         ("retired", &retired_set),
   9030         ("yank-only", &yank_only_set),
   9031     ];
   9032     for idx in 0..class_sets.len() {
   9033         for other_idx in (idx + 1)..class_sets.len() {
   9034             let overlap = class_sets[idx]
   9035                 .1
   9036                 .intersection(class_sets[other_idx].1)
   9037                 .cloned()
   9038                 .collect::<BTreeSet<_>>();
   9039             if !overlap.is_empty() {
   9040                 return Err(format!(
   9041                     "release classification overlap is not allowed between {} and {}: {}",
   9042                     class_sets[idx].0,
   9043                     class_sets[other_idx].0,
   9044                     join_set(&overlap)
   9045                 ));
   9046             }
   9047         }
   9048     }
   9049 
   9050     let mut combined = public_set.clone();
   9051     combined.extend(internal_set.iter().cloned());
   9052     combined.extend(deferred_set.iter().cloned());
   9053     combined.extend(retired_set.iter().cloned());
   9054     combined.extend(yank_only_set.iter().cloned());
   9055     if combined != workspace_packages {
   9056         let missing = workspace_packages
   9057             .difference(&combined)
   9058             .cloned()
   9059             .collect::<BTreeSet<_>>();
   9060         let extra = combined
   9061             .difference(&workspace_packages)
   9062             .cloned()
   9063             .collect::<BTreeSet<_>>();
   9064         return Err(format!(
   9065             "release classification sets are missing workspace crates: {}; release classification sets include unknown crates: {}",
   9066             join_set(&missing),
   9067             join_set(&extra)
   9068         ));
   9069     }
   9070 
   9071     if publish_order_set != public_set {
   9072         let missing = public_set
   9073             .difference(&publish_order_set)
   9074             .cloned()
   9075             .collect::<BTreeSet<_>>();
   9076         let extra = publish_order_set
   9077             .difference(&public_set)
   9078             .cloned()
   9079             .collect::<BTreeSet<_>>();
   9080         return Err(format!(
   9081             "publish_order.crates is missing publish crates: {}; publish_order.crates has non-publish crates: {}",
   9082             join_set(&missing),
   9083             join_set(&extra)
   9084         ));
   9085     }
   9086 
   9087     let order_index = publish_order
   9088         .iter()
   9089         .enumerate()
   9090         .map(|(idx, name)| (name.clone(), idx))
   9091         .collect::<BTreeMap<_, _>>();
   9092     let dependencies = read_workspace_package_dependencies(workspace_root)
   9093         .expect("workspace package manifests were already parsed");
   9094     for crate_name in &public_set {
   9095         let crate_deps = &dependencies[crate_name];
   9096         let crate_order = order_index[crate_name];
   9097         for dep in crate_deps {
   9098             if !public_set.contains(dep) {
   9099                 continue;
   9100             }
   9101             let dep_order = order_index[dep];
   9102             if dep_order >= crate_order {
   9103                 return Err(format!(
   9104                     "publish order must place dependency {} before {}",
   9105                     dep, crate_name
   9106                 ));
   9107             }
   9108         }
   9109     }
   9110 
   9111     if validate_publication_control(&release, &publish_configs, false)? {
   9112         return Ok(());
   9113     }
   9114     for crate_name in &public_set {
   9115         let publish = publish_configs[crate_name].as_ref();
   9116         if !publish_config_is_public(publish) {
   9117             return Err(format!(
   9118                 "public crate {} must set publish = [\"crates-io\"]",
   9119                 crate_name
   9120             ));
   9121         }
   9122     }
   9123     for crate_name in internal_set
   9124         .iter()
   9125         .chain(deferred_set.iter())
   9126         .chain(retired_set.iter())
   9127         .chain(yank_only_set.iter())
   9128     {
   9129         let publish = publish_configs[crate_name].as_ref();
   9130         if !publish_config_is_non_public(publish) {
   9131             return Err(format!(
   9132                 "non-public crate {} must set publish = false",
   9133                 crate_name
   9134             ));
   9135         }
   9136     }
   9137     Ok(())
   9138 }
   9139 
   9140 #[derive(Clone, Copy)]
   9141 enum OperationAuthorityProfile {
   9142     CapsuleCanonical,
   9143     #[cfg(test)]
   9144     Generic,
   9145 }
   9146 
   9147 pub fn validate_release_preflight(workspace_root: &Path) -> Result<(), String> {
   9148     validate_release_preflight_with_override(workspace_root, None)
   9149 }
   9150 
   9151 pub fn validate_release_preflight_with_override(
   9152     workspace_root: &Path,
   9153     release_policy_override: Option<PathBuf>,
   9154 ) -> Result<(), String> {
   9155     validate_release_preflight_with_override_and_profile(
   9156         workspace_root,
   9157         release_policy_override,
   9158         OperationAuthorityProfile::CapsuleCanonical,
   9159     )
   9160 }
   9161 
   9162 fn validate_release_preflight_with_override_and_profile(
   9163     workspace_root: &Path,
   9164     release_policy_override: Option<PathBuf>,
   9165     authority_profile: OperationAuthorityProfile,
   9166 ) -> Result<(), String> {
   9167     let bundle = load_contract_bundle(workspace_root)?;
   9168     validate_contract_bundle_with_release_policy_override_and_profile(
   9169         &bundle,
   9170         release_policy_override.clone(),
   9171         authority_profile,
   9172     )?;
   9173     let release = load_release_contract_with_override(
   9174         workspace_root,
   9175         bundle.version.contract.version.as_str(),
   9176         release_policy_override,
   9177     )?;
   9178     let policy =
   9179         load_coverage_policy(&bundle.root).expect("validated contract includes coverage policy");
   9180     let publish_crates = collect_unique_set(
   9181         &release.public_crates(),
   9182         if release.uses_classification() {
   9183             "classification.public"
   9184         } else {
   9185             "publish.crates"
   9186         },
   9187     )
   9188     .expect("validated contract enforces unique public crates");
   9189     let required_crate_list = policy
   9190         .required_crates()
   9191         .expect("validated contract includes required crates");
   9192     let required_crates = collect_unique_set(&required_crate_list, "required.crates")
   9193         .expect("validated contract enforces unique required.crates");
   9194     validate_publishable_dto_tooling_sources(workspace_root, &publish_crates)?;
   9195     validate_publish_package_metadata(workspace_root, &publish_crates)?;
   9196     validate_required_coverage_summary_with_policy(workspace_root, &required_crates, &policy)?;
   9197     Ok(())
   9198 }
   9199 
   9200 fn validate_contract_bundle_with_release_policy_override(
   9201     bundle: &ContractBundle,
   9202     release_policy_override: Option<PathBuf>,
   9203 ) -> Result<(), String> {
   9204     validate_contract_bundle_with_release_policy_override_and_profile(
   9205         bundle,
   9206         release_policy_override,
   9207         OperationAuthorityProfile::CapsuleCanonical,
   9208     )
   9209 }
   9210 
   9211 fn validate_contract_bundle_with_release_policy_override_and_profile(
   9212     bundle: &ContractBundle,
   9213     release_policy_override: Option<PathBuf>,
   9214     authority_profile: OperationAuthorityProfile,
   9215 ) -> Result<(), String> {
   9216     if bundle.manifest.contract.name.trim().is_empty() {
   9217         return Err("contract name is required".to_string());
   9218     }
   9219     if bundle.manifest.contract.version.trim().is_empty() {
   9220         return Err("contract version is required".to_string());
   9221     }
   9222     if bundle.manifest.contract.source.trim().is_empty() {
   9223         return Err("contract source is required".to_string());
   9224     }
   9225     if bundle.manifest.surface.model_crates.is_empty() {
   9226         return Err("contract surface.model_crates must not be empty".to_string());
   9227     }
   9228     if bundle.manifest.surface.algorithm_crates.is_empty() {
   9229         return Err("contract surface.algorithm_crates must not be empty".to_string());
   9230     }
   9231     validate_surface_metadata(&bundle.manifest.surface)?;
   9232     if bundle.version.contract.version.trim().is_empty() {
   9233         return Err("version.contract.version is required".to_string());
   9234     }
   9235     if bundle.version.contract.stability.trim().is_empty() {
   9236         return Err("version.contract.stability is required".to_string());
   9237     }
   9238     if bundle.version.semver.major_on.is_empty()
   9239         || bundle.version.semver.minor_on.is_empty()
   9240         || bundle.version.semver.patch_on.is_empty()
   9241     {
   9242         return Err("version.semver rules must all be non-empty".to_string());
   9243     }
   9244     if !bundle.version.release_integrity.requires_conformance_pass {
   9245         return Err("release_integrity.requires_conformance_pass must be true".to_string());
   9246     }
   9247     if !bundle
   9248         .version
   9249         .release_integrity
   9250         .requires_contract_manifest_diff
   9251     {
   9252         return Err("release_integrity.requires_contract_manifest_diff must be true".to_string());
   9253     }
   9254     if !bundle.version.release_integrity.requires_release_notes {
   9255         return Err("release_integrity.requires_release_notes must be true".to_string());
   9256     }
   9257     validate_policy_metadata(&bundle.manifest.policy)?;
   9258     let workspace_root = bundle
   9259         .root
   9260         .parent()
   9261         .expect("contract root must have a workspace parent");
   9262     validate_replica_contract(bundle, workspace_root)?;
   9263     validate_operations_contract(bundle, &bundle.operations_manifest, workspace_root)?;
   9264     if matches!(
   9265         authority_profile,
   9266         OperationAuthorityProfile::CapsuleCanonical
   9267     ) {
   9268         validate_capsule_operation_authority(&bundle.operations_manifest, workspace_root)?;
   9269     }
   9270     validate_all_conformance_vectors(workspace_root, &bundle.manifest.contract.version)?;
   9271     validate_core_unit_dimension_variant_order(workspace_root)?;
   9272     validate_coverage_policy_parity(workspace_root, &bundle.root)?;
   9273     validate_version_governance(bundle, workspace_root)?;
   9274     if matches!(
   9275         authority_profile,
   9276         OperationAuthorityProfile::CapsuleCanonical
   9277     ) {
   9278         crate::architecture::validate(workspace_root)?;
   9279     }
   9280     validate_release_publish_policy_with_override_and_control(
   9281         workspace_root,
   9282         &bundle.root,
   9283         bundle.version.contract.version.as_str(),
   9284         release_policy_override,
   9285         matches!(
   9286             authority_profile,
   9287             OperationAuthorityProfile::CapsuleCanonical
   9288         ),
   9289         matches!(
   9290             authority_profile,
   9291             OperationAuthorityProfile::CapsuleCanonical
   9292         ),
   9293     )?;
   9294     Ok(())
   9295 }
   9296 
   9297 #[cfg(test)]
   9298 fn validate_release_publish_policy_with_override(
   9299     workspace_root: &Path,
   9300     contract_root: &Path,
   9301     contract_version: &str,
   9302     release_policy_override: Option<PathBuf>,
   9303 ) -> Result<(), String> {
   9304     validate_release_publish_policy_with_override_and_control(
   9305         workspace_root,
   9306         contract_root,
   9307         contract_version,
   9308         release_policy_override,
   9309         true,
   9310         false,
   9311     )
   9312 }
   9313 
   9314 fn validate_release_publish_policy_with_override_and_control(
   9315     workspace_root: &Path,
   9316     _contract_root: &Path,
   9317     contract_version: &str,
   9318     release_policy_override: Option<PathBuf>,
   9319     require_publication_control: bool,
   9320     require_v1_policy: bool,
   9321 ) -> Result<(), String> {
   9322     let release = load_release_contract_with_override(
   9323         workspace_root,
   9324         contract_version,
   9325         release_policy_override,
   9326     )?;
   9327     if release.release.version.trim().is_empty() {
   9328         return Err("release.version must not be empty".to_string());
   9329     }
   9330     if release.release.version != contract_version {
   9331         return Err(format!(
   9332             "release.version {} must match contract version {}",
   9333             release.release.version, contract_version
   9334         ));
   9335     }
   9336 
   9337     let workspace_packages = workspace_package_names(workspace_root)?
   9338         .into_iter()
   9339         .collect::<BTreeSet<_>>();
   9340     let publish_configs = workspace_package_publish_configs(workspace_root)
   9341         .expect("workspace publish configs are stable");
   9342     if validate_v1_release_policy(
   9343         workspace_root,
   9344         &release,
   9345         &workspace_packages,
   9346         &publish_configs,
   9347         require_v1_policy,
   9348     )?
   9349     .is_some()
   9350     {
   9351         return Ok(());
   9352     }
   9353     let uses_classification = release.uses_classification();
   9354     let public_field = if uses_classification {
   9355         "classification.public"
   9356     } else {
   9357         "publish.crates"
   9358     };
   9359     let internal_field = if uses_classification {
   9360         "classification.internal"
   9361     } else {
   9362         "internal.crates"
   9363     };
   9364 
   9365     let public_set = collect_unique_set(&release.public_crates(), public_field)?;
   9366     let internal_set = collect_unique_set(&release.internal_crates(), internal_field)?;
   9367     let deferred_set = collect_unique_set(&release.deferred_crates(), "classification.deferred")?;
   9368     let retired_set = collect_unique_set(&release.retired_crates(), "classification.retired")?;
   9369     let yank_only_set =
   9370         collect_unique_set(&release.yank_only_crates(), "classification.yank_only")?;
   9371     let publish_order = &release.publish_order.crates;
   9372     let publish_order_set = collect_unique_set(publish_order, "publish_order.crates")?;
   9373 
   9374     let class_sets = [
   9375         ("public", &public_set),
   9376         ("internal", &internal_set),
   9377         ("deferred", &deferred_set),
   9378         ("retired", &retired_set),
   9379         ("yank-only", &yank_only_set),
   9380     ];
   9381     for idx in 0..class_sets.len() {
   9382         for other_idx in (idx + 1)..class_sets.len() {
   9383             let overlap = class_sets[idx]
   9384                 .1
   9385                 .intersection(class_sets[other_idx].1)
   9386                 .cloned()
   9387                 .collect::<BTreeSet<_>>();
   9388             if !overlap.is_empty() {
   9389                 return Err(format!(
   9390                     "release classification overlap is not allowed between {} and {}: {}",
   9391                     class_sets[idx].0,
   9392                     class_sets[other_idx].0,
   9393                     join_set(&overlap)
   9394                 ));
   9395             }
   9396         }
   9397     }
   9398 
   9399     let mut combined = public_set.clone();
   9400     combined.extend(internal_set.iter().cloned());
   9401     combined.extend(deferred_set.iter().cloned());
   9402     combined.extend(retired_set.iter().cloned());
   9403     combined.extend(yank_only_set.iter().cloned());
   9404     if combined != workspace_packages {
   9405         let missing = workspace_packages
   9406             .difference(&combined)
   9407             .cloned()
   9408             .collect::<BTreeSet<_>>();
   9409         let extra = combined
   9410             .difference(&workspace_packages)
   9411             .cloned()
   9412             .collect::<BTreeSet<_>>();
   9413         return Err(format!(
   9414             "release classification sets are missing workspace crates: {}; release classification sets include unknown crates: {}",
   9415             join_set(&missing),
   9416             join_set(&extra)
   9417         ));
   9418     }
   9419 
   9420     if publish_order_set != public_set {
   9421         let missing = public_set
   9422             .difference(&publish_order_set)
   9423             .cloned()
   9424             .collect::<BTreeSet<_>>();
   9425         let extra = publish_order_set
   9426             .difference(&public_set)
   9427             .cloned()
   9428             .collect::<BTreeSet<_>>();
   9429         return Err(format!(
   9430             "publish_order.crates is missing publish crates: {}; publish_order.crates has non-publish crates: {}",
   9431             join_set(&missing),
   9432             join_set(&extra)
   9433         ));
   9434     }
   9435 
   9436     let order_index = publish_order
   9437         .iter()
   9438         .enumerate()
   9439         .map(|(idx, name)| (name.clone(), idx))
   9440         .collect::<BTreeMap<_, _>>();
   9441     let dependencies = read_workspace_package_dependencies(workspace_root)
   9442         .expect("workspace package manifests were already parsed");
   9443     for crate_name in &public_set {
   9444         let crate_deps = &dependencies[crate_name];
   9445         let crate_order = order_index[crate_name];
   9446         for dep in crate_deps {
   9447             if !public_set.contains(dep) {
   9448                 continue;
   9449             }
   9450             let dep_order = order_index[dep];
   9451             if dep_order >= crate_order {
   9452                 return Err(format!(
   9453                     "publish order must place dependency {} before {}",
   9454                     dep, crate_name
   9455                 ));
   9456             }
   9457         }
   9458     }
   9459 
   9460     if validate_publication_control(&release, &publish_configs, require_publication_control)? {
   9461         return Ok(());
   9462     }
   9463     for crate_name in &public_set {
   9464         let publish = publish_configs[crate_name].as_ref();
   9465         if !publish_config_is_public(publish) {
   9466             return Err(format!(
   9467                 "public crate {} must set publish = [\"crates-io\"]",
   9468                 crate_name
   9469             ));
   9470         }
   9471     }
   9472     for crate_name in internal_set
   9473         .iter()
   9474         .chain(deferred_set.iter())
   9475         .chain(retired_set.iter())
   9476         .chain(yank_only_set.iter())
   9477     {
   9478         let publish = publish_configs[crate_name].as_ref();
   9479         if !publish_config_is_non_public(publish) {
   9480             return Err(format!(
   9481                 "non-public crate {} must set publish = false",
   9482                 crate_name
   9483             ));
   9484         }
   9485     }
   9486 
   9487     Ok(())
   9488 }
   9489 
   9490 pub fn load_contract_bundle(workspace_root: &Path) -> Result<ContractBundle, String> {
   9491     reject_legacy_contract_roots(workspace_root)?;
   9492     let root = contract_root(workspace_root);
   9493     let manifest = parse_toml::<ContractManifest>(&root.join("manifest.toml"))?;
   9494     let version = parse_toml::<VersionPolicy>(&root.join("version.toml"))?;
   9495     let replica =
   9496         parse_toml::<ReplicaContractManifest>(&workspace_root.join(REPLICA_CONTRACT_RELATIVE))?;
   9497     let operations_manifest =
   9498         parse_toml::<OperationsContractManifest>(&root.join("operations.toml"))?;
   9499     Ok(ContractBundle {
   9500         root,
   9501         manifest,
   9502         version,
   9503         replica,
   9504         operations_manifest,
   9505     })
   9506 }
   9507 
   9508 fn reject_legacy_contract_roots(workspace_root: &Path) -> Result<(), String> {
   9509     for relative in ["spec", "policy"] {
   9510         let legacy_root = workspace_root.join(relative);
   9511         if legacy_root.exists() {
   9512             return Err(format!(
   9513                 "legacy contract root {} is forbidden; use contracts/",
   9514                 legacy_root.display()
   9515             ));
   9516         }
   9517     }
   9518     Ok(())
   9519 }
   9520 
   9521 pub fn validate_contract_bundle(bundle: &ContractBundle) -> Result<(), String> {
   9522     validate_contract_bundle_with_release_policy_override(bundle, None)
   9523 }
   9524 
   9525 #[cfg(test)]
   9526 mod tests {
   9527     use super::*;
   9528     use std::collections::BTreeSet;
   9529     use std::fs;
   9530     use std::path::{Path, PathBuf};
   9531     use std::time::{SystemTime, UNIX_EPOCH};
   9532 
   9533     const SYNTHETIC_CONFORMANCE_VECTOR: &str = r#"{
   9534   "suite": "synthetic",
   9535   "contract_version": "1.0.0",
   9536   "vectors": [
   9537     {
   9538       "id": "synthetic_vector_001",
   9539       "kind": "synthetic.operation",
   9540       "input": {},
   9541       "expected": {}
   9542     }
   9543   ]
   9544 }
   9545 "#;
   9546 
   9547     fn workspace_root() -> PathBuf {
   9548         let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
   9549         manifest_dir
   9550             .join("../..")
   9551             .canonicalize()
   9552             .expect("canonical workspace root")
   9553     }
   9554 
   9555     #[test]
   9556     fn sqlite_runtime_policy_matches_the_exact_migration_inventory() {
   9557         validate_sqlite_runtime_contract(&workspace_root())
   9558             .expect("current SQLx and SQLite migration policy must validate");
   9559     }
   9560 
   9561     #[test]
   9562     fn sqlite_dependency_inventory_uses_the_selected_package_not_its_alias() {
   9563         let manifest = toml::from_str::<toml::Value>(
   9564             r#"[dependencies]
   9565 database = { package = "rusqlite", version = "1" }
   9566 sqlx = { version = "1" }
   9567 "#,
   9568         )
   9569         .expect("dependency fixture");
   9570         let dependencies = manifest
   9571             .get("dependencies")
   9572             .and_then(toml::Value::as_table)
   9573             .expect("dependency table");
   9574         let mut found = BTreeSet::new();
   9575         collect_matching_dependencies(
   9576             "fixture",
   9577             dependencies,
   9578             &|dependency| dependency == "rusqlite",
   9579             &mut found,
   9580         );
   9581         assert_eq!(found, BTreeSet::from(["fixture:rusqlite".to_string()]));
   9582     }
   9583 
   9584     fn validate_generic_contract_bundle(bundle: &ContractBundle) -> Result<(), String> {
   9585         validate_contract_bundle_with_release_policy_override_and_profile(
   9586             bundle,
   9587             None,
   9588             OperationAuthorityProfile::Generic,
   9589         )
   9590     }
   9591 
   9592     fn validate_generic_release_preflight(workspace_root: &Path) -> Result<(), String> {
   9593         validate_release_preflight_with_override_and_profile(
   9594             workspace_root,
   9595             None,
   9596             OperationAuthorityProfile::Generic,
   9597         )
   9598     }
   9599 
   9600     fn current_post_authority() -> (OperationsContractManifest, ConformanceVectorFile) {
   9601         let root = workspace_root();
   9602         let manifest =
   9603             parse_toml::<OperationsContractManifest>(&root.join("contracts/operations.toml"))
   9604                 .expect("current operations manifest");
   9605         let vector =
   9606             parse_json::<ConformanceVectorFile>(&root.join(POST_CONFORMANCE_VECTOR_RELATIVE))
   9607                 .expect("current post conformance vector");
   9608         (manifest, vector)
   9609     }
   9610 
   9611     fn current_admission_authority() -> (OperationsContractManifest, ConformanceVectorFile) {
   9612         let root = workspace_root();
   9613         let manifest =
   9614             parse_toml::<OperationsContractManifest>(&root.join("contracts/operations.toml"))
   9615                 .expect("current operations manifest");
   9616         let vector = parse_json::<ConformanceVectorFile>(
   9617             &root.join(admission_authority::ADMISSION_CONFORMANCE_VECTOR_RELATIVE),
   9618         )
   9619         .expect("current verified admission conformance vector");
   9620         (manifest, vector)
   9621     }
   9622 
   9623     fn current_comment_authority() -> (OperationsContractManifest, ConformanceVectorFile) {
   9624         let root = workspace_root();
   9625         let manifest =
   9626             parse_toml::<OperationsContractManifest>(&root.join("contracts/operations.toml"))
   9627                 .expect("current operations manifest");
   9628         let vector =
   9629             parse_json::<ConformanceVectorFile>(&root.join(COMMENT_CONFORMANCE_VECTOR_RELATIVE))
   9630                 .expect("current Comment conformance vector");
   9631         (manifest, vector)
   9632     }
   9633 
   9634     fn current_deletion_authority() -> (
   9635         OperationsContractManifest,
   9636         ConformanceVectorFile,
   9637         ConformanceVectorFile,
   9638     ) {
   9639         let root = workspace_root();
   9640         let manifest =
   9641             parse_toml::<OperationsContractManifest>(&root.join("contracts/operations.toml"))
   9642                 .expect("current operations manifest");
   9643         let request_vector =
   9644             parse_json::<ConformanceVectorFile>(&root.join(DELETION_CONFORMANCE_VECTOR_RELATIVE))
   9645                 .expect("current deletion conformance vector");
   9646         let suppression_vector = parse_json::<ConformanceVectorFile>(
   9647             &root.join(DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE),
   9648         )
   9649         .expect("current deletion suppression conformance vector");
   9650         (manifest, request_vector, suppression_vector)
   9651     }
   9652 
   9653     fn current_food_availability_authority() -> (OperationsContractManifest, ConformanceVectorFile)
   9654     {
   9655         let root = workspace_root();
   9656         let manifest =
   9657             parse_toml::<OperationsContractManifest>(&root.join("contracts/operations.toml"))
   9658                 .expect("current operations manifest");
   9659         let vector = parse_json::<ConformanceVectorFile>(
   9660             &root.join(FOOD_AVAILABILITY_CONFORMANCE_VECTOR_RELATIVE),
   9661         )
   9662         .expect("current FoodAvailability conformance vector");
   9663         (manifest, vector)
   9664     }
   9665 
   9666     fn current_knowledge_manifest_authority() -> (String, ConformanceVectorFile) {
   9667         let root = workspace_root();
   9668         let manifest = fs::read_to_string(root.join(KNOWLEDGE_MANIFEST_RELATIVE))
   9669             .expect("current knowledge manifest");
   9670         let vector =
   9671             parse_json::<ConformanceVectorFile>(&root.join(KNOWLEDGE_MANIFEST_AND_DECODE_RELATIVE))
   9672                 .expect("current knowledge manifest conformance vector");
   9673         (manifest, vector)
   9674     }
   9675 
   9676     fn temp_root(prefix: &str) -> PathBuf {
   9677         let nanos = SystemTime::now()
   9678             .duration_since(UNIX_EPOCH)
   9679             .expect("clock")
   9680             .as_nanos();
   9681         let root = std::env::temp_dir().join(format!("radroots_xtask_{prefix}_{nanos}"));
   9682         fs::create_dir_all(&root).expect("create temp root");
   9683         root
   9684     }
   9685 
   9686     fn write_file(path: &Path, content: &str) {
   9687         let _ = fs::create_dir_all(path.parent().unwrap_or(Path::new("")));
   9688         fs::write(path, content).expect("write file");
   9689     }
   9690 
   9691     fn required_thresholds() -> CoverageThresholds {
   9692         CoverageThresholds {
   9693             fail_under_exec_lines: COVERAGE_REQUIRED_THRESHOLD,
   9694             fail_under_functions: COVERAGE_REQUIRED_THRESHOLD,
   9695             fail_under_regions: COVERAGE_REQUIRED_THRESHOLD,
   9696             fail_under_branches: COVERAGE_REQUIRED_THRESHOLD,
   9697             require_branches: true,
   9698         }
   9699     }
   9700 
   9701     fn coverage_thresholds(value: f64, require_branches: bool) -> CoverageThresholds {
   9702         CoverageThresholds {
   9703             fail_under_exec_lines: value,
   9704             fail_under_functions: value,
   9705             fail_under_regions: value,
   9706             fail_under_branches: value,
   9707             require_branches,
   9708         }
   9709     }
   9710 
   9711     struct TestCoverageRefreshRow<'a> {
   9712         crate_name: &'a str,
   9713         status: &'a str,
   9714         thresholds: CoverageThresholds,
   9715         exec: f64,
   9716         func: f64,
   9717         branch: Option<f64>,
   9718         region: f64,
   9719         report_pass: bool,
   9720     }
   9721 
   9722     fn passing_coverage_row(crate_name: &str) -> TestCoverageRefreshRow<'_> {
   9723         TestCoverageRefreshRow {
   9724             crate_name,
   9725             status: "pass",
   9726             thresholds: coverage_thresholds(COVERAGE_REQUIRED_THRESHOLD, true),
   9727             exec: 100.0,
   9728             func: 100.0,
   9729             branch: Some(100.0),
   9730             region: 100.0,
   9731             report_pass: true,
   9732         }
   9733     }
   9734 
   9735     fn coverage_refresh_branch_value(branch: Option<f64>) -> String {
   9736         branch
   9737             .map(|value| value.to_string())
   9738             .unwrap_or_else(|| "unavailable".to_string())
   9739     }
   9740 
   9741     fn write_test_coverage_gate_report(root: &Path, row: &TestCoverageRefreshRow<'_>) -> String {
   9742         let report_relative = format!("target/coverage/{}/gate-report.json", row.crate_name);
   9743         let report_path = root.join(&report_relative);
   9744         let fail_reasons = if row.report_pass {
   9745             Vec::<&str>::new()
   9746         } else {
   9747             vec!["policy gate failed"]
   9748         };
   9749         let report = serde_json::json!({
   9750             "scope": row.crate_name,
   9751             "thresholds": {
   9752                 "executable_lines": row.thresholds.fail_under_exec_lines,
   9753                 "functions": row.thresholds.fail_under_functions,
   9754                 "regions": row.thresholds.fail_under_regions,
   9755                 "branches": row.thresholds.fail_under_branches,
   9756                 "branches_required": row.thresholds.require_branches
   9757             },
   9758             "measured": {
   9759                 "executable_lines_percent": row.exec,
   9760                 "executable_lines_source": "da",
   9761                 "functions_percent": row.func,
   9762                 "branches_percent": row.branch,
   9763                 "branches_available": row.branch.is_some(),
   9764                 "summary_lines_percent": row.exec,
   9765                 "summary_regions_percent": row.region
   9766             },
   9767             "counts": {
   9768                 "executable_lines": {
   9769                     "covered": 1,
   9770                     "total": 1
   9771                 },
   9772                 "branches": {
   9773                     "covered": if row.branch.is_some() { 1 } else { 0 },
   9774                     "total": if row.branch.is_some() { 1 } else { 0 }
   9775                 }
   9776             },
   9777             "result": {
   9778                 "pass": row.report_pass,
   9779                 "fail_reasons": fail_reasons
   9780             }
   9781         });
   9782         let json =
   9783             serde_json::to_string_pretty(&report).expect("serialize test coverage gate report");
   9784         write_file(&report_path, &format!("{json}\n"));
   9785         report_relative
   9786     }
   9787 
   9788     fn write_test_coverage_refresh(root: &Path, rows: &[TestCoverageRefreshRow<'_>]) {
   9789         let mut refresh_rows = String::from("crate\tstatus\texec\tfunc\tbranch\tregion\treport\n");
   9790         for row in rows {
   9791             let report_relative = write_test_coverage_gate_report(root, row);
   9792             refresh_rows.push_str(&format!(
   9793                 "{}\t{}\t{}\t{}\t{}\t{}\t{}\n",
   9794                 row.crate_name,
   9795                 row.status,
   9796                 row.exec,
   9797                 row.func,
   9798                 coverage_refresh_branch_value(row.branch),
   9799                 row.region,
   9800                 report_relative
   9801             ));
   9802         }
   9803         write_file(
   9804             &root
   9805                 .join("target")
   9806                 .join("coverage")
   9807                 .join("coverage-refresh.tsv"),
   9808             &refresh_rows,
   9809         );
   9810     }
   9811 
   9812     fn create_synthetic_workspace(prefix: &str) -> PathBuf {
   9813         let root = temp_root(prefix);
   9814         write_file(
   9815             &root.join("contracts/crates/release_v1/radroots_crates_release_v1.toml"),
   9816             r#"spec_id = "radroots.crates.release.v1"
   9817 package_count = 2
   9818 
   9819 [repositories.lib]
   9820 version = "1.0.0"
   9821 packages = ["radroots_a", "radroots_b"]
   9822 
   9823 [repositories.sdk]
   9824 version = "0.1.0"
   9825 packages = []
   9826 
   9827 [[package]]
   9828 name = "radroots_a"
   9829 
   9830 [[package]]
   9831 name = "radroots_b"
   9832 "#,
   9833         );
   9834         write_file(
   9835             &root.join("Cargo.toml"),
   9836             r#"[workspace]
   9837 members = ["crates/a", "crates/b"]
   9838 resolver = "2"
   9839 
   9840 [workspace.package]
   9841 version = "1.0.0"
   9842 
   9843 [workspace.dependencies]
   9844 radroots_a = { path = "crates/a", version = "=1.0.0" }
   9845 radroots_b = { path = "crates/b", version = "=1.0.0" }
   9846 "#,
   9847         );
   9848         write_file(
   9849             &root.join("crates").join("a").join("Cargo.toml"),
   9850             r#"[package]
   9851 name = "radroots_a"
   9852 publish = ["crates-io"]
   9853 version = "1.0.0"
   9854 edition = "2024"
   9855 authors = ["Radroots Test"]
   9856 rust-version = "1.97"
   9857 license = "MIT OR Apache-2.0"
   9858 description = "crate a"
   9859 repository = "https://example.com/a"
   9860 homepage = "https://example.com/a"
   9861 documentation = "https://docs.rs/radroots_a"
   9862 readme = "README.md"
   9863 keywords = ["radroots"]
   9864 categories = ["data-structures"]
   9865 include = ["src/**", "tests/**", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
   9866 
   9867 [package.metadata.docs.rs]
   9868 features = []
   9869 "#,
   9870         );
   9871         write_file(&root.join("LICENSE-APACHE"), "Apache license\n");
   9872         write_file(&root.join("LICENSE-MIT"), "MIT license\n");
   9873         for relative in ["README.md", "LICENSE-APACHE", "LICENSE-MIT"] {
   9874             let contents = if relative == "README.md" {
   9875                 "# radroots_a\n".to_owned()
   9876             } else {
   9877                 fs::read_to_string(root.join(relative)).expect("read synthetic package metadata")
   9878             };
   9879             write_file(&root.join("crates").join("a").join(relative), &contents);
   9880         }
   9881         write_file(
   9882             &root.join("crates").join("b").join("Cargo.toml"),
   9883             r#"[package]
   9884 name = "radroots_b"
   9885 version = "1.0.0"
   9886 edition = "2024"
   9887 publish = false
   9888 
   9889 [features]
   9890 default = ["std"]
   9891 std = []
   9892 legacy-ingest = ["std"]
   9893 "#,
   9894         );
   9895         write_file(
   9896             &root.join("crates").join("b").join("src").join("lib.rs"),
   9897             r#"#[cfg(feature = "legacy-ingest")]
   9898 pub mod ingest;
   9899 
   9900 #[cfg(feature = "legacy-ingest")]
   9901 pub use ingest::{radroots_replica_ingest_event, RadrootsReplicaIngestOutcome};
   9902 "#,
   9903         );
   9904         write_file(
   9905             &root.join("crates").join("b").join("src").join("types.rs"),
   9906             r#"use serde::{Deserialize, Serialize};
   9907 
   9908 pub const RADROOTS_REPLICA_TRANSFER_VERSION: u32 = 2;
   9909 
   9910 #[derive(Clone, Debug, Serialize, Deserialize)]
   9911 #[serde(deny_unknown_fields)]
   9912 pub struct RadrootsReplicaFarmSelector;
   9913 
   9914 #[derive(Clone, Debug, Serialize, Deserialize)]
   9915 #[serde(deny_unknown_fields)]
   9916 pub struct RadrootsReplicaSyncOptions;
   9917 
   9918 #[derive(Clone, Debug, Serialize, Deserialize)]
   9919 #[serde(deny_unknown_fields)]
   9920 pub struct RadrootsReplicaSyncRequest;
   9921 "#,
   9922         );
   9923         write_file(
   9924             &root.join("crates").join("b").join("src").join("emit.rs"),
   9925             r#"pub fn radroots_replica_sync_all_with_options() {}
   9926 
   9927 #[cfg(test)]
   9928 mod tests {}
   9929 "#,
   9930         );
   9931         write_file(
   9932             &root.join("Cargo.lock"),
   9933             r#"version = 4
   9934 
   9935 [[package]]
   9936 name = "radroots_a"
   9937 version = "1.0.0"
   9938 
   9939 [[package]]
   9940 name = "radroots_b"
   9941 version = "1.0.0"
   9942 "#,
   9943         );
   9944         write_file(
   9945             &root.join("crates").join("core").join("src").join("unit.rs"),
   9946             r#"pub enum UnitDimension {
   9947     Count,
   9948     Mass,
   9949     Volume,
   9950 }
   9951 "#,
   9952         );
   9953 
   9954         write_file(
   9955             &root.join("contracts").join("manifest.toml"),
   9956             r#"[contract]
   9957 name = "radroots_contract"
   9958 version = "1.0.0"
   9959 source = "synthetic"
   9960 
   9961 [surface]
   9962 model_crates = ["radroots_a"]
   9963 algorithm_crates = ["radroots_b"]
   9964 
   9965 [surface.internal_replica_crates]
   9966 schema = "radroots_a"
   9967 storage = "radroots_b"
   9968 sync = "radroots_b"
   9969 
   9970 [policy]
   9971 exclude_internal_workspace_crates = true
   9972 require_reproducible_exports = true
   9973 require_conformance_vectors = true
   9974 
   9975 [policy.replica]
   9976 forbid_legacy_alias_identifiers = true
   9977 require_transport_agnostic_sync_contract = true
   9978 require_deterministic_emit_ingest = true
   9979 "#,
   9980         );
   9981         write_file(
   9982             &root.join("contracts").join("version.toml"),
   9983             r#"[contract]
   9984 version = "1.0.0"
   9985 stability = "alpha"
   9986 
   9987 [semver]
   9988 major_on = ["breaking"]
   9989 minor_on = ["feature"]
   9990 patch_on = ["fix"]
   9991 
   9992 [release_integrity]
   9993 requires_conformance_pass = true
   9994 requires_contract_manifest_diff = true
   9995 requires_release_notes = true
   9996 "#,
   9997         );
   9998         write_file(
   9999             &root.join("contracts").join("replica.toml"),
  10000             r#"schema_version = 1
  10001 
  10002 [contract]
  10003 name = "radroots_replica_contract"
  10004 version = "1.0.0"
  10005 purpose = "synthetic deterministic replica sync"
  10006 
  10007 [crate_family]
  10008 schema = "radroots_a"
  10009 storage = "radroots_b"
  10010 sync = "radroots_b"
  10011 
  10012 [policy]
  10013 transport_agnostic_sync_core = true
  10014 deterministic_emit_and_ingest = true
  10015 forbid_legacy_alias_identifiers = true
  10016 profile_event_emission = "excluded"
  10017 unknown_sync_request_fields = "reject"
  10018 classified_listing_signature_verification = "required_before_state"
  10019 classified_listing_head_selection = "raw_before_profile"
  10020 classified_listing_operational_projection = "operational_partition_only"
  10021 classified_listing_excluded_or_rejected_head = "remove_projection_and_advance"
  10022 classified_listing_head_only_ingest = "reject_require_profile_aware"
  10023 legacy_bare_envelope_ingest = "explicit_non_default_feature_only"
  10024 legacy_ingest_feature = "legacy-ingest"
  10025 phase_1_ingest_replacement = "none"
  10026 future_product_ingest_input = "store_produced_verified_valid_visible_admission"
  10027 
  10028 [transfer]
  10029 version = 2
  10030 source = "crates/b/src/types.rs"
  10031 constant = "RADROOTS_REPLICA_TRANSFER_VERSION"
  10032 "#,
  10033         );
  10034         write_file(
  10035             &root.join("contracts").join("coverage.toml"),
  10036             r#"[gate]
  10037 fail_under_exec_lines = 90.0
  10038 fail_under_functions = 90.0
  10039 fail_under_regions = 90.0
  10040 fail_under_branches = 90.0
  10041 require_branches = true
  10042 
  10043 [required]
  10044 crates = ["radroots_a", "radroots_b"]
  10045 "#,
  10046         );
  10047         write_file(
  10048             &root.join(CHANGELOG_RELATIVE),
  10049             "# Changelog\n\n## [1.0.0]\n\n- Synthetic breaking release.\n",
  10050         );
  10051         for (canonical_relative, mirror_relative) in CONFORMANCE_VECTOR_MIRRORS {
  10052             write_file(&root.join(canonical_relative), SYNTHETIC_CONFORMANCE_VECTOR);
  10053             write_file(&root.join(mirror_relative), SYNTHETIC_CONFORMANCE_VECTOR);
  10054         }
  10055         write_file(
  10056             &root.join(RELEASES_ROOT_RELATIVE).join("1.0.0.toml"),
  10057             r#"schema_version = 1
  10058 
  10059 [release]
  10060 version = "1.0.0"
  10061 previous_version = "0.1.0-alpha.2"
  10062 contract_base_version = "1.0.0"
  10063 status = "unreleased"
  10064 
  10065 [artifacts]
  10066 changelog = "CHANGELOG.md"
  10067 manifest = "contracts/manifest.toml"
  10068 operations = "contracts/operations.toml"
  10069 replica = "contracts/replica.toml"
  10070 conformance = "contracts/conformance"
  10071 publish_policy = "contracts/releases/publish_policy.toml"
  10072 
  10073 [[changes]]
  10074 id = "synthetic-major-release"
  10075 classification = "breaking"
  10076 semver_impacts = ["breaking"]
  10077 summary = "Exercise synthetic major release governance."
  10078 "#,
  10079         );
  10080         write_file(
  10081             &root_release_policy_path(&root),
  10082             r#"[release]
  10083 version = "1.0.0"
  10084 
  10085 [publish]
  10086 crates = ["radroots_a"]
  10087 
  10088 [internal]
  10089 crates = ["radroots_b"]
  10090 
  10091 [publish_order]
  10092 crates = ["radroots_a"]
  10093 "#,
  10094         );
  10095         write_test_coverage_refresh(
  10096             &root,
  10097             &[
  10098                 passing_coverage_row("radroots_a"),
  10099                 passing_coverage_row("radroots_b"),
  10100             ],
  10101         );
  10102         add_operation_contract_files(&root);
  10103         root
  10104     }
  10105 
  10106     fn add_operation_contract_files(root: &Path) {
  10107         write_file(
  10108             &root.join("contracts").join("operations.toml"),
  10109             r#"[contract]
  10110 name = "radroots_contract"
  10111 version = "1.0.0"
  10112 source = "synthetic"
  10113 
  10114 [public]
  10115 domains = ["profile", "farm", "operational_listing", "trade"]
  10116 
  10117 [shared_types]
  10118 public = [
  10119   "Nip01EventWireParts",
  10120   "GenericEventDraft",
  10121   "SignedEvent",
  10122   "EventEnvelope",
  10123   "EventRef",
  10124   "EventPtr",
  10125   "ClassifiedListingAddress",
  10126   "AuthoredProfile",
  10127   "RadrootsInboundProfileMetadata",
  10128   "Farm",
  10129   "OperationalListing",
  10130 ]
  10131 
  10132 [errors]
  10133 classes = ["encode_error", "parse_error", "validation_error", "address_error"]
  10134 
  10135 [implementation_provenance]
  10136 model_crates = ["radroots_a"]
  10137 algorithm_crates = ["radroots_b"]
  10138 
  10139 [operations.profile_build_authored_draft]
  10140 domain = "profile"
  10141 id = "profile.build_authored_draft"
  10142 stability = "beta"
  10143 inputs = ["AuthoredProfile"]
  10144 outputs = ["Nip01EventWireParts"]
  10145 error_class = "encode_error"
  10146 deterministic = true
  10147 signing = "native"
  10148 transport = "native"
  10149 
  10150 [operations.profile_build_authored_draft.implementation]
  10151 rust_modules = ["crates/core/src/unit.rs"]
  10152 rust_types = ["radroots_event::profile::AuthoredProfile"]
  10153 
  10154 [operations.profile_build_authored_draft.conformance]
  10155 vector = "contracts/conformance/vectors/profile/metadata.v1.json"
  10156 
  10157 [operations.operational_listing_build_draft]
  10158 domain = "operational_listing"
  10159 id = "operational_listing.build_draft"
  10160 stability = "beta"
  10161 inputs = ["OperationalListing"]
  10162 outputs = ["Nip01EventWireParts"]
  10163 error_class = "encode_error"
  10164 deterministic = true
  10165 signing = "native"
  10166 transport = "native"
  10167 
  10168 [operations.operational_listing_build_draft.implementation]
  10169 rust_modules = ["crates/core/src/unit.rs"]
  10170 rust_types = ["radroots_event::listing::operational::OperationalListing"]
  10171 
  10172 [operations.operational_listing_build_draft.conformance]
  10173 vector = "contracts/conformance/vectors/operational_listing/build_draft.v1.json"
  10174 "#,
  10175         );
  10176         write_file(
  10177             &root
  10178                 .join("contracts")
  10179                 .join("conformance")
  10180                 .join("schema")
  10181                 .join("vector.schema.json"),
  10182             r#"{
  10183   "$schema": "http://json-schema.org/draft-07/schema#",
  10184   "$id": "https://radroots.org/core/conformance/vector.schema.json",
  10185   "title": "radroots core conformance vector",
  10186   "type": "object",
  10187   "required": ["suite", "contract_version", "vectors"],
  10188   "properties": {
  10189     "suite": {
  10190       "type": "string",
  10191       "minLength": 1
  10192     },
  10193     "contract_version": {
  10194       "type": "string",
  10195       "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
  10196     },
  10197     "vectors": {
  10198       "type": "array",
  10199       "items": {
  10200         "type": "object",
  10201         "required": ["id", "kind", "input"],
  10202         "properties": {
  10203           "id": {
  10204             "type": "string",
  10205             "minLength": 1
  10206           },
  10207           "kind": {
  10208             "type": "string",
  10209             "minLength": 1
  10210           },
  10211           "input": {},
  10212           "expected": {},
  10213           "expected_error_contains": {
  10214             "type": "string",
  10215             "minLength": 1
  10216           }
  10217         },
  10218         "oneOf": [
  10219           {
  10220             "required": ["expected"],
  10221             "not": {"required": ["expected_error_contains"]}
  10222           },
  10223           {
  10224             "required": ["expected_error_contains"],
  10225             "not": {"required": ["expected"]}
  10226           }
  10227         ],
  10228         "additionalProperties": false
  10229       }
  10230     }
  10231   },
  10232   "additionalProperties": false
  10233 }
  10234 "#,
  10235         );
  10236         write_file(
  10237             &root
  10238                 .join("contracts")
  10239                 .join("conformance")
  10240                 .join("vectors")
  10241                 .join("profile")
  10242                 .join("metadata.v1.json"),
  10243             SYNTHETIC_CONFORMANCE_VECTOR,
  10244         );
  10245         let operational_listing_vector = r#"{
  10246   "suite": "operational_listing",
  10247   "contract_version": "1.0.0",
  10248   "vectors": [
  10249     {
  10250       "id": "operational_listing_build_draft_minimal_001",
  10251       "kind": "operational_listing.build_draft",
  10252       "input": {},
  10253       "expected": {}
  10254     }
  10255   ]
  10256 }
  10257 "#;
  10258         write_file(
  10259             &root
  10260                 .join("contracts")
  10261                 .join("conformance")
  10262                 .join("vectors")
  10263                 .join("operational_listing")
  10264                 .join("build_draft.v1.json"),
  10265             operational_listing_vector,
  10266         );
  10267         write_file(
  10268             &root
  10269                 .join("crates")
  10270                 .join("event_codec")
  10271                 .join("tests")
  10272                 .join("fixtures")
  10273                 .join("operational_listing_build_draft.v1.json"),
  10274             operational_listing_vector,
  10275         );
  10276     }
  10277 
  10278     fn write_root_release_policy(root: &Path, raw: &str) {
  10279         write_file(&root_release_policy_path(root), raw);
  10280     }
  10281 
  10282     fn configure_root_release_policy_workspace(root: &Path) {
  10283         write_file(
  10284             &root.join("Cargo.toml"),
  10285             r#"[workspace]
  10286 members = ["crates/a", "crates/b", "crates/c", "crates/d", "crates/e"]
  10287 resolver = "2"
  10288 
  10289 [workspace.package]
  10290 version = "1.0.0"
  10291 
  10292 [workspace.dependencies]
  10293 radroots_a = { path = "crates/a", version = "=1.0.0" }
  10294 radroots_b = { path = "crates/b", version = "=1.0.0" }
  10295 radroots_c = { path = "crates/c", version = "=1.0.0" }
  10296 radroots_d = { path = "crates/d", version = "=1.0.0" }
  10297 radroots_e = { path = "crates/e", version = "=1.0.0" }
  10298 "#,
  10299         );
  10300         for crate_name in ["c", "d", "e"] {
  10301             write_file(
  10302                 &root.join("crates").join(crate_name).join("Cargo.toml"),
  10303                 &format!(
  10304                     r#"[package]
  10305 name = "radroots_{crate_name}"
  10306 version = "1.0.0"
  10307 edition = "2024"
  10308 publish = false
  10309 "#
  10310                 ),
  10311             );
  10312         }
  10313         write_file(
  10314             &root.join("Cargo.lock"),
  10315             r#"version = 4
  10316 
  10317 [[package]]
  10318 name = "radroots_a"
  10319 version = "1.0.0"
  10320 
  10321 [[package]]
  10322 name = "radroots_b"
  10323 version = "1.0.0"
  10324 
  10325 [[package]]
  10326 name = "radroots_c"
  10327 version = "1.0.0"
  10328 
  10329 [[package]]
  10330 name = "radroots_d"
  10331 version = "1.0.0"
  10332 
  10333 [[package]]
  10334 name = "radroots_e"
  10335 version = "1.0.0"
  10336 "#,
  10337         );
  10338         write_file(
  10339             &root.join("contracts").join("coverage.toml"),
  10340             r#"[gate]
  10341 fail_under_exec_lines = 90.0
  10342 fail_under_functions = 90.0
  10343 fail_under_regions = 90.0
  10344 fail_under_branches = 90.0
  10345 require_branches = true
  10346 
  10347 [required]
  10348 crates = ["radroots_a", "radroots_b", "radroots_c", "radroots_d", "radroots_e"]
  10349 "#,
  10350         );
  10351         write_test_coverage_refresh(
  10352             root,
  10353             &[
  10354                 passing_coverage_row("radroots_a"),
  10355                 passing_coverage_row("radroots_b"),
  10356                 passing_coverage_row("radroots_c"),
  10357                 passing_coverage_row("radroots_d"),
  10358                 passing_coverage_row("radroots_e"),
  10359             ],
  10360         );
  10361         let _ = fs::remove_file(root_release_policy_path(root));
  10362     }
  10363 
  10364     #[test]
  10365     fn validate_current_contract_bundle() {
  10366         let root = workspace_root();
  10367         let bundle = load_contract_bundle(&root).expect("load contract");
  10368         validate_contract_bundle(&bundle).expect("validate contract");
  10369     }
  10370 
  10371     #[test]
  10372     fn knowledge_manifest_vector_authority_rejects_registry_drift() {
  10373         let (manifest, vector) = current_knowledge_manifest_authority();
  10374         validate_knowledge_manifest_vector_semantics(&manifest, &vector)
  10375             .expect("current knowledge manifest vector authority");
  10376 
  10377         let (manifest, mut vector) = current_knowledge_manifest_authority();
  10378         let case = vector
  10379             .vectors
  10380             .iter_mut()
  10381             .find(|entry| entry.id == "knowledge_manifest_fields_valid_001")
  10382             .expect("knowledge manifest case");
  10383         case.input
  10384             .as_object_mut()
  10385             .expect("knowledge manifest input")
  10386             .insert(
  10387                 "registry".to_string(),
  10388                 Value::String("radroots_event_contract_registry_v1".to_string()),
  10389             );
  10390         let error = validate_knowledge_manifest_vector_semantics(&manifest, &vector)
  10391             .expect_err("stale registry marker must fail");
  10392         assert!(error.contains("registry marker drift"), "{error}");
  10393 
  10394         let (manifest, mut vector) = current_knowledge_manifest_authority();
  10395         let case = vector
  10396             .vectors
  10397             .iter_mut()
  10398             .find(|entry| entry.id == "knowledge_manifest_fields_valid_001")
  10399             .expect("knowledge manifest case");
  10400         case.expected
  10401             .as_mut()
  10402             .expect("knowledge manifest expected output")
  10403             .as_object_mut()
  10404             .expect("knowledge manifest expected output object")
  10405             .insert("registry_version".to_string(), Value::from(1_u64));
  10406         let error = validate_knowledge_manifest_vector_semantics(&manifest, &vector)
  10407             .expect_err("stale expected registry version must fail");
  10408         assert!(error.contains("expected registry_version drift"), "{error}");
  10409     }
  10410 
  10411     #[test]
  10412     fn knowledge_manifest_artifacts_are_atomic_fresh_and_shape_checked() {
  10413         let root = temp_root("knowledge_manifest_artifacts");
  10414         let generated =
  10415             write_knowledge_contract_manifest_artifacts(&root).expect("write manifest artifacts");
  10416         assert_eq!(
  10417             generated,
  10418             expected_knowledge_contract_manifest_json().expect("expected manifest")
  10419         );
  10420         assert_eq!(
  10421             validate_knowledge_contract_manifest_artifacts(&root)
  10422                 .expect("fresh manifest artifacts"),
  10423             generated
  10424         );
  10425 
  10426         let manifest_path = root.join(KNOWLEDGE_MANIFEST_RELATIVE);
  10427         let mut extra_lf = fs::read_to_string(&manifest_path).expect("read manifest");
  10428         extra_lf.push('\n');
  10429         fs::write(&manifest_path, extra_lf).expect("write noncanonical manifest");
  10430         let error = validate_knowledge_contract_manifest_artifacts(&root)
  10431             .expect_err("noncanonical manifest must fail");
  10432         assert!(error.contains("exactly one LF"), "{error}");
  10433 
  10434         write_knowledge_contract_manifest_artifacts(&root).expect("restore manifest artifacts");
  10435         let mut value: Value =
  10436             serde_json::from_slice(&fs::read(&manifest_path).expect("read restored manifest"))
  10437                 .expect("parse restored manifest");
  10438         value["contract_count"] = Value::from(0_u64);
  10439         let mut mismatched = serde_json::to_string_pretty(&value).expect("serialize mismatch");
  10440         mismatched.push('\n');
  10441         fs::write(&manifest_path, mismatched).expect("write count mismatch");
  10442         let error = validate_knowledge_contract_manifest_artifacts(&root)
  10443             .expect_err("count mismatch must fail");
  10444         assert!(error.contains("contract_count"), "{error}");
  10445 
  10446         let _ = fs::remove_dir_all(root);
  10447     }
  10448 
  10449     #[test]
  10450     fn strict_post_release_record_governs_public_boundary_breaks() {
  10451         let root = workspace_root();
  10452         let bundle = load_contract_bundle(&root).expect("load current contract bundle");
  10453         let major_impacts = bundle
  10454             .version
  10455             .semver
  10456             .major_on
  10457             .iter()
  10458             .map(String::as_str)
  10459             .collect::<BTreeSet<_>>();
  10460         for impact in [
  10461             "add_exported_field",
  10462             "change_exported_function_signature",
  10463             "change_exported_constant_value",
  10464         ] {
  10465             assert!(
  10466                 major_impacts.contains(impact),
  10467                 "version policy must govern {impact} as a major impact"
  10468             );
  10469         }
  10470         assert!(
  10471             bundle
  10472                 .version
  10473                 .semver
  10474                 .minor_on
  10475                 .iter()
  10476                 .any(|impact| impact == "add_exported_constant"),
  10477             "version policy must govern add_exported_constant as a minor impact"
  10478         );
  10479 
  10480         let release =
  10481             parse_toml::<ReleaseRecord>(&root.join("contracts/releases/1.0.0-alpha.1.toml"))
  10482                 .expect("current release record");
  10483         let change = release
  10484             .changes
  10485             .iter()
  10486             .find(|change| change.id == "strict-kind-one-product-profiles")
  10487             .expect("strict kind-one release change");
  10488         let impacts = change
  10489             .semver_impacts
  10490             .iter()
  10491             .map(String::as_str)
  10492             .collect::<BTreeSet<_>>();
  10493         for impact in [
  10494             "remove_exported_type",
  10495             "add_exported_constant",
  10496             "add_exported_field",
  10497             "change_exported_function_signature",
  10498             "change_exported_enum_variant",
  10499             "change_exported_constant_value",
  10500         ] {
  10501             assert!(
  10502                 impacts.contains(impact),
  10503                 "strict kind-one release change must declare {impact}"
  10504             );
  10505         }
  10506     }
  10507 
  10508     #[test]
  10509     fn post_operation_authority_rejects_manifest_and_inventory_drift() {
  10510         let (manifest, vector) = current_post_authority();
  10511         validate_post_operation_inventory(&manifest, &vector).expect("current post authority");
  10512 
  10513         let (mut manifest, vector) = current_post_authority();
  10514         manifest
  10515             .operations
  10516             .remove("social_update_build_authored_draft");
  10517         let error = validate_post_operation_inventory(&manifest, &vector)
  10518             .expect_err("missing post operation must fail");
  10519         assert!(error.contains("post operation authority drift"));
  10520 
  10521         let (mut manifest, vector) = current_post_authority();
  10522         manifest
  10523             .operations
  10524             .get_mut("social_update_build_authored_draft")
  10525             .expect("Update operation")
  10526             .id = "social.update.wrong".to_string();
  10527         let error = validate_post_operation_inventory(&manifest, &vector)
  10528             .expect_err("wrong post operation ID must fail");
  10529         assert!(error.contains("id drift"));
  10530 
  10531         let (mut manifest, vector) = current_post_authority();
  10532         manifest
  10533             .operations
  10534             .get_mut("social_update_build_authored_draft")
  10535             .expect("Update operation")
  10536             .conformance
  10537             .vector = "contracts/conformance/vectors/profile/metadata.v1.json".to_string();
  10538         let error = validate_post_operation_inventory(&manifest, &vector)
  10539             .expect_err("wrong post vector path must fail");
  10540         assert!(error.contains("conformance.vector drift"));
  10541 
  10542         let (mut manifest, vector) = current_post_authority();
  10543         manifest
  10544             .operations
  10545             .get_mut("social_update_build_authored_draft")
  10546             .expect("Update operation")
  10547             .conformance
  10548             .case_kinds[0] = "social.ask.build_authored_draft.valid".to_string();
  10549         let error = validate_post_operation_inventory(&manifest, &vector)
  10550             .expect_err("wrong post case prefix must fail");
  10551         assert!(error.contains("must start with social.update.build_authored_draft."));
  10552 
  10553         let (mut manifest, vector) = current_post_authority();
  10554         manifest
  10555             .operations
  10556             .get_mut("social_update_build_authored_draft")
  10557             .expect("Update operation")
  10558             .conformance
  10559             .case_kinds
  10560             .pop();
  10561         let error = validate_post_operation_inventory(&manifest, &vector)
  10562             .expect_err("missing post case kind must fail");
  10563         assert!(error.contains("conformance.case_kinds drift"));
  10564 
  10565         let (mut manifest, vector) = current_post_authority();
  10566         let operation = manifest
  10567             .operations
  10568             .get_mut("social_update_build_authored_draft")
  10569             .expect("Update operation");
  10570         operation.conformance.case_kinds[1] = operation.conformance.case_kinds[0].clone();
  10571         let error = validate_post_operation_inventory(&manifest, &vector)
  10572             .expect_err("duplicate post case kind must fail");
  10573         assert!(error.contains("duplicate value"), "{error}");
  10574 
  10575         let (manifest, mut vector) = current_post_authority();
  10576         vector.vectors.push(ConformanceVectorEntry {
  10577             id: "unclaimed_post_case".to_string(),
  10578             kind: "social.post.unclaimed.valid".to_string(),
  10579             input: Value::Object(Default::default()),
  10580             expected: Some(Value::Object(Default::default())),
  10581             expected_error_contains: None,
  10582         });
  10583         let error = validate_post_operation_inventory(&manifest, &vector)
  10584             .expect_err("unclaimed post vector kind must fail");
  10585         assert!(error.contains("is not claimed by exactly one operation"));
  10586 
  10587         let (manifest, mut vector) = current_post_authority();
  10588         vector.vectors.remove(
  10589             vector
  10590                 .vectors
  10591                 .iter()
  10592                 .position(|entry| entry.kind == "social.post.project_verified_event.valid")
  10593                 .expect("project valid case"),
  10594         );
  10595         let error = validate_post_operation_inventory(&manifest, &vector)
  10596             .expect_err("post vector count drift must fail");
  10597         assert!(error.contains("post conformance vector inventory drift"));
  10598     }
  10599 
  10600     #[test]
  10601     fn verified_admission_authority_rejects_manifest_fixture_and_secret_drift() {
  10602         let (manifest, vector) = current_admission_authority();
  10603         admission_authority::validate_admission_operation_inventory(&manifest, &vector)
  10604             .expect("current verified admission authority");
  10605 
  10606         let (mut manifest, vector) = current_admission_authority();
  10607         manifest.operations.remove("event_admit_verified");
  10608         let error = admission_authority::validate_admission_operation_inventory(&manifest, &vector)
  10609             .expect_err("missing central admission operation must fail");
  10610         assert!(error.contains("operation authority drift"), "{error}");
  10611 
  10612         let (mut manifest, vector) = current_admission_authority();
  10613         manifest
  10614             .shared_types
  10615             .public
  10616             .retain(|value| value != "RadrootsEventAdmissionError");
  10617         let error = admission_authority::validate_admission_operation_inventory(&manifest, &vector)
  10618             .expect_err("missing central admission public type must fail");
  10619         assert!(error.contains("requires shared public type"), "{error}");
  10620 
  10621         let (manifest, mut vector) = current_admission_authority();
  10622         vector.vectors[0]
  10623             .input
  10624             .as_object_mut()
  10625             .expect("admission input")
  10626             .insert(
  10627                 "secret_key".to_string(),
  10628                 Value::String("forbidden".to_string()),
  10629             );
  10630         let error = admission_authority::validate_admission_operation_inventory(&manifest, &vector)
  10631             .expect_err("fixture secret material must fail exact input inventory");
  10632         assert!(error.contains("field inventory drift"), "{error}");
  10633 
  10634         let (manifest, mut vector) = current_admission_authority();
  10635         vector.vectors[0].id = "renamed_admission_case".to_string();
  10636         let error = admission_authority::validate_admission_operation_inventory(&manifest, &vector)
  10637             .expect_err("renamed admission vector must fail exact inventory");
  10638         assert!(error.contains("unexpected id"), "{error}");
  10639     }
  10640 
  10641     #[test]
  10642     fn post_operation_authority_rejects_another_vector_namespace_operation() {
  10643         let (mut manifest, vector) = current_post_authority();
  10644         let mut unexpected = manifest
  10645             .operations
  10646             .remove("social_reaction_build_tags")
  10647             .expect("unrelated social operation");
  10648         unexpected.id = "social.update.shadow".to_string();
  10649         manifest
  10650             .operations
  10651             .insert("social_update_shadow".to_string(), unexpected);
  10652 
  10653         let error = validate_post_operation_inventory(&manifest, &vector)
  10654             .expect_err("another-vector post namespace operation must fail");
  10655         assert!(error.contains("post operation authority drift"), "{error}");
  10656         assert!(error.contains("social_update_shadow"), "{error}");
  10657     }
  10658 
  10659     #[test]
  10660     fn post_operation_authority_rejects_metadata_drift() {
  10661         let (mut manifest, vector) = current_post_authority();
  10662         manifest
  10663             .operations
  10664             .get_mut("social_update_build_authored_draft")
  10665             .expect("Update operation")
  10666             .stability = "stable".to_string();
  10667 
  10668         let error = validate_post_operation_inventory(&manifest, &vector)
  10669             .expect_err("post operation metadata drift must fail");
  10670         assert!(error.contains("stability drift"), "{error}");
  10671     }
  10672 
  10673     #[test]
  10674     fn post_operation_authority_rejects_required_public_type_removal() {
  10675         let (mut manifest, vector) = current_post_authority();
  10676         manifest
  10677             .shared_types
  10678             .public
  10679             .retain(|value| value != "RadrootsPostAdmissionOutcome");
  10680 
  10681         let error = validate_post_operation_inventory(&manifest, &vector)
  10682             .expect_err("required post public type removal must fail");
  10683         assert!(
  10684             error.contains(
  10685                 "post operation authority requires shared public type RadrootsPostAdmissionOutcome"
  10686             ),
  10687             "{error}"
  10688         );
  10689     }
  10690 
  10691     #[test]
  10692     fn post_operation_authority_rejects_same_count_vector_id_replacement() {
  10693         let (manifest, mut vector) = current_post_authority();
  10694         vector
  10695             .vectors
  10696             .iter_mut()
  10697             .find(|entry| entry.id == "authored_update_wire")
  10698             .expect("authored Update case")
  10699             .id = "authored_update_wire_replacement".to_string();
  10700 
  10701         let error = validate_post_operation_inventory(&manifest, &vector)
  10702             .expect_err("same-count post vector ID replacement must fail");
  10703         assert!(error.contains("post conformance vector inventory drift"));
  10704     }
  10705 
  10706     #[test]
  10707     fn post_operation_authority_rejects_vector_id_kind_drift() {
  10708         let (manifest, mut vector) = current_post_authority();
  10709         let update_position = vector
  10710             .vectors
  10711             .iter()
  10712             .position(|entry| entry.id == "authored_update_wire")
  10713             .expect("authored Update case");
  10714         let ask_position = vector
  10715             .vectors
  10716             .iter()
  10717             .position(|entry| entry.id == "authored_ask_wire")
  10718             .expect("authored Ask case");
  10719         let update_kind = vector.vectors[update_position].kind.clone();
  10720         vector.vectors[update_position].kind = vector.vectors[ask_position].kind.clone();
  10721         vector.vectors[ask_position].kind = update_kind;
  10722 
  10723         let error = validate_post_operation_inventory(&manifest, &vector)
  10724             .expect_err("post vector ID-to-kind drift must fail");
  10725         assert!(error.contains("post conformance vector inventory drift"));
  10726     }
  10727 
  10728     #[test]
  10729     fn comment_operation_authority_rejects_contract_drift() {
  10730         let (manifest, vector) = current_comment_authority();
  10731         validate_comment_operation_inventory(&manifest, &vector)
  10732             .expect("current Comment operation authority");
  10733 
  10734         let (mut manifest, vector) = current_comment_authority();
  10735         manifest
  10736             .operations
  10737             .remove("social_comment_build_authored_draft");
  10738         let error = validate_comment_operation_inventory(&manifest, &vector)
  10739             .expect_err("missing Comment operation must fail");
  10740         assert!(
  10741             error.contains("comment operation authority drift"),
  10742             "{error}"
  10743         );
  10744 
  10745         let (mut manifest, vector) = current_comment_authority();
  10746         let renamed = manifest
  10747             .operations
  10748             .remove("social_comment_project_verified_event")
  10749             .expect("Comment projection operation");
  10750         manifest
  10751             .operations
  10752             .insert("social_comment_project_event".to_string(), renamed);
  10753         let error = validate_comment_operation_inventory(&manifest, &vector)
  10754             .expect_err("renamed Comment operation must fail");
  10755         assert!(
  10756             error.contains("comment operation authority drift"),
  10757             "{error}"
  10758         );
  10759         assert!(error.contains("social_comment_project_event"), "{error}");
  10760 
  10761         let (mut manifest, vector) = current_comment_authority();
  10762         manifest
  10763             .operations
  10764             .get_mut("social_comment_verify_and_admit_event")
  10765             .expect("Comment admission operation")
  10766             .signing = "none".to_string();
  10767         let error = validate_comment_operation_inventory(&manifest, &vector)
  10768             .expect_err("Comment operation metadata drift must fail");
  10769         assert!(error.contains("signing drift"), "{error}");
  10770 
  10771         let (mut manifest, vector) = current_comment_authority();
  10772         manifest
  10773             .shared_types
  10774             .public
  10775             .retain(|value| value != "RadrootsInboundNip22TopLevelEventReference");
  10776         let error = validate_comment_operation_inventory(&manifest, &vector)
  10777             .expect_err("required Comment public type removal must fail");
  10778         assert!(
  10779             error.contains(
  10780                 "comment operation authority requires shared public type RadrootsInboundNip22TopLevelEventReference"
  10781             ),
  10782             "{error}"
  10783         );
  10784     }
  10785 
  10786     #[test]
  10787     fn comment_operation_authority_rejects_vector_inventory_drift() {
  10788         let (manifest, mut vector) = current_comment_authority();
  10789         vector
  10790             .vectors
  10791             .iter_mut()
  10792             .find(|entry| entry.id == "authored_top_event_listing")
  10793             .expect("authored top-level event case")
  10794             .id = "authored_top_event_listing_replacement".to_string();
  10795         let error = validate_comment_operation_inventory(&manifest, &vector)
  10796             .expect_err("same-count Comment vector ID replacement must fail");
  10797         assert!(
  10798             error.contains("comment conformance vector inventory drift"),
  10799             "{error}"
  10800         );
  10801 
  10802         let (manifest, mut vector) = current_comment_authority();
  10803         vector.vectors.push(ConformanceVectorEntry {
  10804             id: "unclaimed_comment_case".to_string(),
  10805             kind: "social.comment.project_verified_event.shadow".to_string(),
  10806             input: Value::Object(Default::default()),
  10807             expected: Some(Value::Object(Default::default())),
  10808             expected_error_contains: None,
  10809         });
  10810         let error = validate_comment_operation_inventory(&manifest, &vector)
  10811             .expect_err("unclaimed Comment vector kind must fail");
  10812         assert!(
  10813             error.contains("is not claimed by exactly one operation"),
  10814             "{error}"
  10815         );
  10816     }
  10817 
  10818     #[test]
  10819     fn comment_vector_namespace_rejects_legacy_owners() {
  10820         let canonical = PathBuf::from(COMMENT_CONFORMANCE_VECTOR_RELATIVE);
  10821         let legacy = PathBuf::from("contracts/conformance/vectors/social/mvp.v1.json");
  10822         let vector = ConformanceVectorFile {
  10823             suite: "legacy".to_string(),
  10824             contract_version: "1.0.0".to_string(),
  10825             vectors: vec![ConformanceVectorEntry {
  10826                 id: "legacy_comment".to_string(),
  10827                 kind: "social.comment.build_tags".to_string(),
  10828                 input: Value::Object(Default::default()),
  10829                 expected: Some(Value::Object(Default::default())),
  10830                 expected_error_contains: None,
  10831             }],
  10832         };
  10833 
  10834         let error = validate_comment_vector_namespace(&legacy, &canonical, &vector)
  10835             .expect_err("legacy Comment vector namespace must fail");
  10836         assert!(error.contains("outside canonical vector"), "{error}");
  10837         validate_comment_vector_namespace(&canonical, &canonical, &vector)
  10838             .expect("canonical Comment vector owns the namespace");
  10839     }
  10840 
  10841     #[test]
  10842     fn deletion_operation_authority_rejects_contract_drift() {
  10843         let (manifest, request_vector, suppression_vector) = current_deletion_authority();
  10844         validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10845             .expect("current deletion operation authority");
  10846 
  10847         let (mut manifest, request_vector, suppression_vector) = current_deletion_authority();
  10848         manifest
  10849             .operations
  10850             .remove("social_deletion_request_project_verified_event");
  10851         let error =
  10852             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10853                 .expect_err("missing deletion operation must fail");
  10854         assert!(
  10855             error.contains("deletion operation authority drift"),
  10856             "{error}"
  10857         );
  10858 
  10859         let (mut manifest, request_vector, suppression_vector) = current_deletion_authority();
  10860         manifest
  10861             .shared_types
  10862             .public
  10863             .push("RadrootsNip09DeletionUnauthorizedEffect".to_string());
  10864         let error =
  10865             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10866                 .expect_err("unexpected deletion public type must fail");
  10867         assert!(
  10868             error.contains("deletion operation public-type authority drift"),
  10869             "{error}"
  10870         );
  10871 
  10872         let (mut manifest, request_vector, suppression_vector) = current_deletion_authority();
  10873         manifest
  10874             .operations
  10875             .get_mut("social_deletion_request_verify_and_admit_event")
  10876             .expect("admission operation")
  10877             .conformance
  10878             .case_kinds
  10879             .pop();
  10880         let error =
  10881             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10882                 .expect_err("missing deletion case kind must fail");
  10883         assert!(error.contains("conformance.case_kinds drift"), "{error}");
  10884 
  10885         let (mut manifest, request_vector, suppression_vector) = current_deletion_authority();
  10886         manifest
  10887             .operations
  10888             .get_mut("social_deletion_request_evaluate_suppression")
  10889             .expect("suppression operation")
  10890             .conformance
  10891             .vector = DELETION_CONFORMANCE_VECTOR_RELATIVE.to_string();
  10892         let error =
  10893             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10894                 .expect_err("suppression vector ownership drift must fail");
  10895         assert!(error.contains("conformance.vector drift"), "{error}");
  10896     }
  10897 
  10898     #[test]
  10899     fn deletion_operation_authority_rejects_vector_inventory_drift() {
  10900         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  10901         request_vector
  10902             .vectors
  10903             .iter_mut()
  10904             .find(|entry| entry.id == "nip09_authored_event_target_min_kind_empty_content")
  10905             .expect("authored deletion vector")
  10906             .id = "nip09_authored_event_target_min_kind_replacement".to_string();
  10907         let error =
  10908             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10909                 .expect_err("same-count deletion vector ID replacement must fail");
  10910         assert!(
  10911             error.contains("deletion conformance vector inventory drift"),
  10912             "{error}"
  10913         );
  10914 
  10915         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  10916         let source = request_vector
  10917             .vectors
  10918             .iter()
  10919             .find(|entry| entry.id == "nip09_project_signed_event_target_without_k")
  10920             .expect("valid signed deletion vector");
  10921         let input = source.input.clone();
  10922         let expected = source.expected.clone();
  10923         request_vector.vectors.push(ConformanceVectorEntry {
  10924             id: "nip09_unclaimed_case".to_string(),
  10925             kind: "social.deletion_request.unclaimed.valid".to_string(),
  10926             input,
  10927             expected,
  10928             expected_error_contains: None,
  10929         });
  10930         let error =
  10931             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10932                 .expect_err("unclaimed deletion vector kind must fail");
  10933         assert!(
  10934             error.contains("is not claimed by exactly one operation"),
  10935             "{error}"
  10936         );
  10937 
  10938         let (manifest, request_vector, mut suppression_vector) = current_deletion_authority();
  10939         suppression_vector
  10940             .vectors
  10941             .iter_mut()
  10942             .find(|entry| entry.id == "nip09_suppress_no_requests_visible")
  10943             .expect("visible suppression vector")
  10944             .id = "nip09_suppress_replacement_visible".to_string();
  10945         let error =
  10946             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10947                 .expect_err("same-count suppression vector ID replacement must fail");
  10948         assert!(
  10949             error.contains("deletion suppression conformance vector inventory drift"),
  10950             "{error}"
  10951         );
  10952     }
  10953 
  10954     #[test]
  10955     fn deletion_operation_authority_rejects_generation_and_effect_metadata() {
  10956         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  10957         request_vector
  10958             .vectors
  10959             .iter_mut()
  10960             .find(|entry| entry.id == "nip09_authored_event_target_min_kind_empty_content")
  10961             .expect("authored deletion vector")
  10962             .input
  10963             .as_object_mut()
  10964             .expect("authored input")
  10965             .insert("SeEd".to_string(), Value::from(7_u64));
  10966         let error =
  10967             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10968                 .expect_err("generation seed metadata must fail");
  10969         assert!(error.contains("forbidden metadata key"), "{error}");
  10970 
  10971         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  10972         request_vector
  10973             .vectors
  10974             .iter_mut()
  10975             .find(|entry| entry.id == "nip09_project_signed_event_target_without_k")
  10976             .expect("signed deletion vector")
  10977             .input
  10978             .as_object_mut()
  10979             .expect("signed input")
  10980             .insert("trace".to_string(), Value::Bool(true));
  10981         let error =
  10982             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  10983                 .expect_err("extra signed input key must fail");
  10984         assert!(error.contains("input keys drift"), "{error}");
  10985 
  10986         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  10987         request_vector
  10988             .vectors
  10989             .iter_mut()
  10990             .find(|entry| entry.id == "nip09_project_signed_event_target_without_k")
  10991             .expect("signed deletion vector")
  10992             .expected
  10993             .as_mut()
  10994             .expect("projection expected")
  10995             .as_object_mut()
  10996             .expect("projection expected object")
  10997             .insert("AuThOrIzAtIoN".to_string(), Value::Bool(true));
  10998         let error =
  10999             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11000                 .expect_err("effect-authority output must fail");
  11001         assert!(error.contains("forbidden metadata key"), "{error}");
  11002 
  11003         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  11004         request_vector
  11005             .vectors
  11006             .iter_mut()
  11007             .find(|entry| entry.id == "nip09_admit_signed_event_target")
  11008             .expect("admission deletion vector")
  11009             .input
  11010             .as_object_mut()
  11011             .expect("signed input")
  11012             .insert(
  11013                 "event_json".to_string(),
  11014                 Value::String(r#"{"content":"NSEC1FORBIDDEN"}"#.to_string()),
  11015             );
  11016         let error =
  11017             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11018                 .expect_err("nsec material must fail");
  11019         assert!(error.contains("forbidden nsec material"), "{error}");
  11020 
  11021         let (manifest, mut request_vector, suppression_vector) = current_deletion_authority();
  11022         request_vector
  11023             .vectors
  11024             .iter_mut()
  11025             .find(|entry| entry.id == "nip09_admit_signed_event_target")
  11026             .expect("admission deletion vector")
  11027             .input
  11028             .as_object_mut()
  11029             .expect("signed input")
  11030             .insert(
  11031                 "event_json".to_string(),
  11032                 Value::String(
  11033                     r#"{"content":"prefix10C5304D6C9AE3A1A16F7860F1CC8F5E3A76225A2663B3A989A0D775919B7DF5suffix"}"#
  11034                         .to_string(),
  11035                 ),
  11036             );
  11037         let error =
  11038             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11039                 .expect_err("approved fixture secret material must fail");
  11040         assert!(
  11041             error.contains("forbidden approved fixture secret material"),
  11042             "{error}"
  11043         );
  11044     }
  11045 
  11046     #[test]
  11047     fn deletion_suppression_authority_rejects_shape_and_material_drift() {
  11048         let (manifest, request_vector, mut suppression_vector) = current_deletion_authority();
  11049         suppression_vector.suite = "nip09_suppression_shadow".to_string();
  11050         let error =
  11051             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11052                 .expect_err("suppression suite drift must fail");
  11053         assert!(
  11054             error.contains("deletion suppression conformance suite drift"),
  11055             "{error}"
  11056         );
  11057 
  11058         let (manifest, request_vector, mut suppression_vector) = current_deletion_authority();
  11059         suppression_vector
  11060             .vectors
  11061             .iter_mut()
  11062             .find(|entry| entry.id == "nip09_suppress_no_requests_visible")
  11063             .expect("visible suppression vector")
  11064             .input
  11065             .as_object_mut()
  11066             .expect("suppression input")
  11067             .insert("seed".to_string(), Value::from(7_u64));
  11068         let error =
  11069             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11070                 .expect_err("suppression generation metadata must fail");
  11071         assert!(error.contains("forbidden metadata key"), "{error}");
  11072 
  11073         let (manifest, request_vector, mut suppression_vector) = current_deletion_authority();
  11074         suppression_vector
  11075             .vectors
  11076             .iter_mut()
  11077             .find(|entry| entry.id == "nip09_suppress_same_author_event_reference")
  11078             .expect("event-reference suppression vector")
  11079             .expected
  11080             .as_mut()
  11081             .expect("suppression expected")
  11082             .as_object_mut()
  11083             .expect("suppression expected object")
  11084             .get_mut("event_reference")
  11085             .expect("event-reference evidence")
  11086             .as_object_mut()
  11087             .expect("event-reference object")
  11088             .insert("request_id".to_string(), Value::String("0".repeat(64)));
  11089         let error =
  11090             validate_deletion_operation_inventory(&manifest, &request_vector, &suppression_vector)
  11091                 .expect_err("evidence not bound to an input request must fail");
  11092         assert!(error.contains("must identify an input request"), "{error}");
  11093     }
  11094 
  11095     #[test]
  11096     fn deletion_vector_namespace_rejects_alternate_owners() {
  11097         let canonical_request = PathBuf::from(DELETION_CONFORMANCE_VECTOR_RELATIVE);
  11098         let canonical_suppression = PathBuf::from(DELETION_SUPPRESSION_CONFORMANCE_VECTOR_RELATIVE);
  11099         let alternate = PathBuf::from("contracts/conformance/vectors/social/mvp.v1.json");
  11100         let vector = ConformanceVectorFile {
  11101             suite: "alternate".to_string(),
  11102             contract_version: "1.0.0".to_string(),
  11103             vectors: vec![ConformanceVectorEntry {
  11104                 id: "nip09_alternate".to_string(),
  11105                 kind: "social.deletion_request.build_authored_draft.valid".to_string(),
  11106                 input: Value::Object(Default::default()),
  11107                 expected: Some(Value::Object(Default::default())),
  11108                 expected_error_contains: None,
  11109             }],
  11110         };
  11111 
  11112         let error = validate_deletion_vector_namespace(
  11113             &alternate,
  11114             &canonical_request,
  11115             &canonical_suppression,
  11116             &vector,
  11117         )
  11118         .expect_err("alternate deletion vector namespace must fail");
  11119         assert!(error.contains("outside canonical vectors"), "{error}");
  11120         validate_deletion_vector_namespace(
  11121             &canonical_request,
  11122             &canonical_request,
  11123             &canonical_suppression,
  11124             &vector,
  11125         )
  11126         .expect("canonical deletion vector owns the namespace");
  11127         validate_deletion_vector_namespace(
  11128             &canonical_suppression,
  11129             &canonical_request,
  11130             &canonical_suppression,
  11131             &vector,
  11132         )
  11133         .expect("canonical deletion suppression vector owns the namespace");
  11134     }
  11135 
  11136     #[test]
  11137     fn food_availability_operation_authority_rejects_contract_drift() {
  11138         let (manifest, vector) = current_food_availability_authority();
  11139         validate_food_availability_operation_inventory(&manifest, &vector)
  11140             .expect("current FoodAvailability operation authority");
  11141 
  11142         let (mut manifest, vector) = current_food_availability_authority();
  11143         manifest
  11144             .operations
  11145             .remove("food_availability_build_authored_draft");
  11146         let error = validate_food_availability_operation_inventory(&manifest, &vector)
  11147             .expect_err("missing FoodAvailability operation must fail");
  11148         assert!(
  11149             error.contains("food availability operation authority drift"),
  11150             "{error}"
  11151         );
  11152 
  11153         let (mut manifest, vector) = current_food_availability_authority();
  11154         manifest
  11155             .shared_types
  11156             .public
  11157             .retain(|value| value != "RadrootsFoodAvailabilityRevisionError");
  11158         let error = validate_food_availability_operation_inventory(&manifest, &vector)
  11159             .expect_err("missing FoodAvailability public type must fail");
  11160         assert!(
  11161             error.contains(
  11162                 "food availability operation authority requires shared public type RadrootsFoodAvailabilityRevisionError"
  11163             ),
  11164             "{error}"
  11165         );
  11166 
  11167         let (mut manifest, vector) = current_food_availability_authority();
  11168         manifest
  11169             .operations
  11170             .get_mut("food_availability_validate_revision")
  11171             .expect("revision operation")
  11172             .conformance
  11173             .case_kinds
  11174             .pop();
  11175         let error = validate_food_availability_operation_inventory(&manifest, &vector)
  11176             .expect_err("missing FoodAvailability case kind must fail");
  11177         assert!(error.contains("conformance.case_kinds drift"), "{error}");
  11178     }
  11179 
  11180     #[test]
  11181     fn food_availability_operation_authority_rejects_vector_inventory_drift() {
  11182         let (manifest, mut vector) = current_food_availability_authority();
  11183         vector
  11184             .vectors
  11185             .iter_mut()
  11186             .find(|entry| entry.id == "food_admission_normalizes_decimal_currency_014")
  11187             .expect("normalization vector")
  11188             .id = "food_admission_normalizes_decimal_currency_replacement".to_string();
  11189         let error = validate_food_availability_operation_inventory(&manifest, &vector)
  11190             .expect_err("same-count FoodAvailability vector replacement must fail");
  11191         assert!(
  11192             error.contains("food availability conformance vector inventory drift"),
  11193             "{error}"
  11194         );
  11195 
  11196         let (manifest, mut vector) = current_food_availability_authority();
  11197         vector.vectors.push(ConformanceVectorEntry {
  11198             id: "food_unclaimed_case".to_string(),
  11199             kind: "food_availability.unclaimed.valid".to_string(),
  11200             input: Value::Object(Default::default()),
  11201             expected: Some(Value::Object(Default::default())),
  11202             expected_error_contains: None,
  11203         });
  11204         let error = validate_food_availability_operation_inventory(&manifest, &vector)
  11205             .expect_err("unclaimed FoodAvailability vector kind must fail");
  11206         assert!(
  11207             error.contains("is not claimed by exactly one operation"),
  11208             "{error}"
  11209         );
  11210     }
  11211 
  11212     #[test]
  11213     fn version_governance_rejects_contract_workspace_and_lock_drift() {
  11214         let root = create_synthetic_workspace("version_governance_drift");
  11215         let mut bundle = load_contract_bundle(&root).expect("load contract");
  11216         bundle.version.contract.version = "1.0.1".to_string();
  11217         let contract_error = validate_contract_version_lockstep(&bundle)
  11218             .expect_err("contract header drift must fail");
  11219         assert!(contract_error.contains("must match manifest contract version"));
  11220 
  11221         let member_path = root.join("crates/a/Cargo.toml");
  11222         let member = fs::read_to_string(&member_path).expect("read member manifest");
  11223         write_file(
  11224             &member_path,
  11225             &member.replace("version = \"1.0.0\"", "version.workspace = true"),
  11226         );
  11227         let member_error = validate_workspace_version_lockstep(&root, "1.0.0")
  11228             .expect_err("inherited member version must fail");
  11229         assert!(member_error.contains("must set an explicit package version"));
  11230         write_file(&member_path, &member);
  11231 
  11232         let workspace_path = root.join("Cargo.toml");
  11233         let workspace = fs::read_to_string(&workspace_path).expect("read workspace manifest");
  11234         write_file(
  11235             &workspace_path,
  11236             &workspace.replacen(
  11237                 "radroots_a = { path = \"crates/a\", version = \"=1.0.0\" }",
  11238                 "radroots_a = { path = \"crates/a\", version = \"1.0.0\" }",
  11239                 1,
  11240             ),
  11241         );
  11242         let requirement_error = validate_workspace_version_lockstep(&root, "1.0.0")
  11243             .expect_err("non-exact internal dependency must fail");
  11244         assert!(requirement_error.contains("exact requirement =1.0.0"));
  11245         write_file(&workspace_path, &workspace);
  11246 
  11247         let lock_path = root.join("Cargo.lock");
  11248         let lock = fs::read_to_string(&lock_path).expect("read Cargo.lock");
  11249         write_file(&lock_path, &lock.replacen("1.0.0", "1.0.1", 1));
  11250         let lock_error = validate_workspace_version_lockstep(&root, "1.0.0")
  11251             .expect_err("lockfile version drift must fail");
  11252         assert!(lock_error.contains("Cargo.lock package radroots_a version"));
  11253 
  11254         write_file(
  11255             &root.join("contracts/crates/release_v1/radroots_crates_release_v1.toml"),
  11256             r#"spec_id = "radroots.crates.release.v1"
  11257 package_count = 0
  11258 package = []
  11259 
  11260 [repositories.lib]
  11261 version = "0.1.0-alpha"
  11262 packages = []
  11263 
  11264 [repositories.sdk]
  11265 version = "0.1.0"
  11266 packages = []
  11267 "#,
  11268         );
  11269         let architecture_error = validate_workspace_version_lockstep(&root, "1.0.0")
  11270             .expect_err("repository version authority must override protocol version");
  11271         assert!(architecture_error.contains("must match library repository version 0.1.0-alpha"));
  11272 
  11273         assert!(parse_semver_version("01.0.0").is_err());
  11274         assert!(parse_semver_version("1.0").is_err());
  11275         assert!(parse_semver_version("1.0.0-alpha_1").is_err());
  11276         let _ = fs::remove_dir_all(root);
  11277     }
  11278 
  11279     #[test]
  11280     fn replica_contract_governance_rejects_metadata_policy_and_transfer_drift() {
  11281         let root = create_synthetic_workspace("replica_contract_drift");
  11282         let bundle = load_contract_bundle(&root).expect("load synthetic contract");
  11283         validate_replica_contract(&bundle, &root).expect("validate replica contract");
  11284 
  11285         let assert_replica_error = |expected: &str, mutator: fn(&mut ContractBundle)| {
  11286             let mut bundle = load_contract_bundle(&root).expect("load synthetic contract");
  11287             mutator(&mut bundle);
  11288             let error = validate_replica_contract(&bundle, &root)
  11289                 .expect_err("replica contract drift must fail");
  11290             assert!(
  11291                 error.contains(expected),
  11292                 "expected `{expected}` in `{error}`"
  11293             );
  11294         };
  11295 
  11296         assert_replica_error("schema_version must be 1", |bundle| {
  11297             bundle.replica.schema_version = 2;
  11298         });
  11299         assert_replica_error("name must be radroots_replica_contract", |bundle| {
  11300             bundle.replica.contract.name = "replica".to_string();
  11301         });
  11302         assert_replica_error("must match manifest contract version", |bundle| {
  11303             bundle.replica.contract.version = "1.0.1".to_string();
  11304         });
  11305         assert_replica_error("purpose is required", |bundle| {
  11306             bundle.replica.contract.purpose.clear();
  11307         });
  11308         assert_replica_error("crate_family.schema", |bundle| {
  11309             bundle.replica.crate_family.schema = "radroots_b".to_string();
  11310         });
  11311         assert_replica_error("must name a workspace package", |bundle| {
  11312             bundle.replica.crate_family.schema = "radroots_missing".to_string();
  11313             bundle
  11314                 .manifest
  11315                 .surface
  11316                 .internal_replica_crates
  11317                 .as_mut()
  11318                 .expect("replica family")
  11319                 .schema = "radroots_missing".to_string();
  11320         });
  11321         assert_replica_error("policy.replica is required", |bundle| {
  11322             bundle.manifest.policy.replica = None;
  11323         });
  11324         assert_replica_error("transport_agnostic_sync_core", |bundle| {
  11325             bundle.replica.policy.transport_agnostic_sync_core = false;
  11326         });
  11327         assert_replica_error("profile_event_emission must be excluded", |bundle| {
  11328             bundle.replica.policy.profile_event_emission = "included".to_string();
  11329         });
  11330         assert_replica_error("unknown_sync_request_fields must be reject", |bundle| {
  11331             bundle.replica.policy.unknown_sync_request_fields = "ignore".to_string();
  11332         });
  11333         assert_replica_error(
  11334             "classified_listing_signature_verification must be required_before_state",
  11335             |bundle| {
  11336                 bundle
  11337                     .replica
  11338                     .policy
  11339                     .classified_listing_signature_verification = "unchecked".to_string();
  11340             },
  11341         );
  11342         assert_replica_error(
  11343             "classified_listing_head_selection must be raw_before_profile",
  11344             |bundle| {
  11345                 bundle.replica.policy.classified_listing_head_selection =
  11346                     "profile_before_raw".to_string();
  11347             },
  11348         );
  11349         assert_replica_error(
  11350             "classified_listing_operational_projection must be operational_partition_only",
  11351             |bundle| {
  11352                 bundle
  11353                     .replica
  11354                     .policy
  11355                     .classified_listing_operational_projection = "all_partitions".to_string();
  11356             },
  11357         );
  11358         assert_replica_error(
  11359             "classified_listing_excluded_or_rejected_head must be remove_projection_and_advance",
  11360             |bundle| {
  11361                 bundle
  11362                     .replica
  11363                     .policy
  11364                     .classified_listing_excluded_or_rejected_head = "retain_projection".to_string();
  11365             },
  11366         );
  11367         assert_replica_error(
  11368             "classified_listing_head_only_ingest must be reject_require_profile_aware",
  11369             |bundle| {
  11370                 bundle.replica.policy.classified_listing_head_only_ingest =
  11371                     "allow_head_only".to_string();
  11372             },
  11373         );
  11374         assert_replica_error(
  11375             "legacy_bare_envelope_ingest must be explicit_non_default_feature_only",
  11376             |bundle| {
  11377                 bundle.replica.policy.legacy_bare_envelope_ingest = "default".to_string();
  11378             },
  11379         );
  11380         assert_replica_error("legacy_ingest_feature must be legacy-ingest", |bundle| {
  11381             bundle.replica.policy.legacy_ingest_feature = "std".to_string();
  11382         });
  11383         assert_replica_error("phase_1_ingest_replacement must be none", |bundle| {
  11384             bundle.replica.policy.phase_1_ingest_replacement = "legacy".to_string();
  11385         });
  11386         assert_replica_error(
  11387             "future_product_ingest_input must be store_produced_verified_valid_visible_admission",
  11388             |bundle| {
  11389                 bundle.replica.policy.future_product_ingest_input = "bare_envelope".to_string();
  11390             },
  11391         );
  11392         assert_replica_error("transfer.version must be 2", |bundle| {
  11393             bundle.replica.transfer.version = 1;
  11394         });
  11395         assert_replica_error("transfer.constant", |bundle| {
  11396             bundle.replica.transfer.constant = "REPLICA_VERSION".to_string();
  11397         });
  11398         assert_replica_error("transfer.source", |bundle| {
  11399             bundle.replica.transfer.source = "crates/a/src/types.rs".to_string();
  11400         });
  11401 
  11402         let source_path = root.join("crates/b/src/types.rs");
  11403         let source = fs::read_to_string(&source_path).expect("read replica types source");
  11404         write_file(
  11405             &source_path,
  11406             &source.replace(
  11407                 "pub const RADROOTS_REPLICA_TRANSFER_VERSION: u32 = 2;",
  11408                 "pub const RADROOTS_REPLICA_TRANSFER_VERSION: u32 = 1;",
  11409             ),
  11410         );
  11411         let bundle = load_contract_bundle(&root).expect("load source-drift contract");
  11412         let source_error = validate_replica_contract(&bundle, &root)
  11413             .expect_err("source constant version drift must fail");
  11414         assert!(source_error.contains("source constant"));
  11415         assert!(source_error.contains("must match contract version 2"));
  11416 
  11417         let _ = fs::remove_dir_all(root);
  11418     }
  11419 
  11420     #[test]
  11421     fn replica_policy_source_witnesses_reject_runtime_drift() {
  11422         let root = create_synthetic_workspace("replica_policy_source_drift");
  11423         let cargo_path = root.join("crates/b/Cargo.toml");
  11424         let lib_path = root.join("crates/b/src/lib.rs");
  11425         let types_path = root.join("crates/b/src/types.rs");
  11426         let emit_path = root.join("crates/b/src/emit.rs");
  11427         let cargo = fs::read_to_string(&cargo_path).expect("read replica cargo manifest");
  11428         let lib = fs::read_to_string(&lib_path).expect("read replica lib source");
  11429         let types = fs::read_to_string(&types_path).expect("read replica types source");
  11430         let emit = fs::read_to_string(&emit_path).expect("read replica emit source");
  11431 
  11432         write_file(
  11433             &cargo_path,
  11434             &cargo.replace("std = []", "std = [\"legacy-ingest\"]"),
  11435         );
  11436         let bundle =
  11437             load_contract_bundle(&root).expect("load transitive default-feature drift contract");
  11438         let default_feature_error = validate_replica_contract(&bundle, &root)
  11439             .expect_err("transitively default legacy ingest feature must fail");
  11440         assert!(default_feature_error.contains("must not be enabled by default features"));
  11441 
  11442         write_file(&cargo_path, &cargo);
  11443         write_file(
  11444             &lib_path,
  11445             &format!(
  11446                 "{}\n/*\n#[cfg(feature = \"legacy-ingest\")]\npub mod ingest;\n*/\n",
  11447                 lib.replace(
  11448                     "#[cfg(feature = \"legacy-ingest\")]\npub mod ingest;",
  11449                     "#[cfg(feature = \"std\")]\npub mod ingest;",
  11450                 )
  11451             ),
  11452         );
  11453         let bundle = load_contract_bundle(&root).expect("load ingest-module drift contract");
  11454         let module_error = validate_replica_contract(&bundle, &root)
  11455             .expect_err("comment-only legacy guard witness must fail");
  11456         assert!(module_error.contains("must be guarded by exact"));
  11457 
  11458         write_file(
  11459             &lib_path,
  11460             &format!("{lib}\npub use ingest::RadrootsReplicaIngestOutcome;\n"),
  11461         );
  11462         let bundle = load_contract_bundle(&root).expect("load second-reexport drift contract");
  11463         let reexport_error = validate_replica_contract(&bundle, &root)
  11464             .expect_err("ungated second ingest re-export must fail");
  11465         assert!(reexport_error.contains("every public replica ingest re-export"));
  11466 
  11467         write_file(
  11468             &lib_path,
  11469             &lib.replacen(
  11470                 "#[cfg(feature = \"legacy-ingest\")]\npub use ingest::{",
  11471                 "#[cfg(any(feature = \"legacy-ingest\", feature = \"std\"))]\npub use ingest::{",
  11472                 1,
  11473             ),
  11474         );
  11475         let bundle = load_contract_bundle(&root).expect("load broadened-reexport contract");
  11476         let broadened_error = validate_replica_contract(&bundle, &root)
  11477             .expect_err("broadened ingest re-export guard must fail");
  11478         assert!(broadened_error.contains("every public replica ingest re-export"));
  11479 
  11480         write_file(
  11481             &lib_path,
  11482             &format!(
  11483                 "{lib}\npub mod nested {{\n    pub use super::ingest::RadrootsReplicaIngestOutcome;\n}}\n"
  11484             ),
  11485         );
  11486         let bundle = load_contract_bundle(&root).expect("load nested-reexport drift contract");
  11487         let nested_error = validate_replica_contract(&bundle, &root)
  11488             .expect_err("ungated nested public ingest re-export must fail");
  11489         assert!(nested_error.contains("every public replica ingest re-export"));
  11490 
  11491         write_file(&lib_path, &lib);
  11492 
  11493         write_file(
  11494             &types_path,
  11495             &types.replace(
  11496                 "#[serde(deny_unknown_fields)]\npub struct RadrootsReplicaSyncOptions",
  11497                 "pub struct RadrootsReplicaSyncOptions",
  11498             ),
  11499         );
  11500         let bundle = load_contract_bundle(&root).expect("load attribute-drift contract");
  11501         let attribute_error = validate_replica_contract(&bundle, &root)
  11502             .expect_err("missing fail-closed request attribute must fail");
  11503         assert!(attribute_error.contains("RadrootsReplicaSyncOptions"));
  11504         assert!(attribute_error.contains("immediately before"));
  11505 
  11506         write_file(
  11507             &types_path,
  11508             &format!("{types}\npub struct include_profiles;\n"),
  11509         );
  11510         let bundle = load_contract_bundle(&root).expect("load retired-option contract");
  11511         let retired_error = validate_replica_contract(&bundle, &root)
  11512             .expect_err("retired include_profiles identifier must fail");
  11513         assert!(retired_error.contains("include_profiles is forbidden"));
  11514 
  11515         write_file(&types_path, &types);
  11516         write_file(
  11517             &emit_path,
  11518             &emit.replace(
  11519                 "#[cfg(test)]\nmod tests {}",
  11520                 "fn emit_profile_event() {}\n\n#[cfg(test)]\nmod tests {}",
  11521             ),
  11522         );
  11523         let bundle = load_contract_bundle(&root).expect("load profile-emitter contract");
  11524         let profile_error = validate_replica_contract(&bundle, &root)
  11525             .expect_err("Profile-related production emitter must fail");
  11526         assert!(profile_error.contains("Profile-related identifier emit_profile_event"));
  11527 
  11528         write_file(
  11529             &emit_path,
  11530             &emit.replace(
  11531                 "#[cfg(test)]\nmod tests {}",
  11532                 "fn emit_kind_zero() { let _event = Event { kind: 0 }; }\n\n#[cfg(test)]\nmod tests {}",
  11533             ),
  11534         );
  11535         let bundle = load_contract_bundle(&root).expect("load literal-kind-zero contract");
  11536         let kind_error = validate_replica_contract(&bundle, &root)
  11537             .expect_err("literal kind-0 production emitter must fail");
  11538         assert!(kind_error.contains("must not construct a literal kind-0 event"));
  11539 
  11540         let _ = fs::remove_dir_all(root);
  11541     }
  11542 
  11543     #[test]
  11544     fn replica_contract_is_required_and_rejects_unknown_fields() {
  11545         let missing_root = create_synthetic_workspace("replica_contract_missing");
  11546         fs::remove_file(missing_root.join(REPLICA_CONTRACT_RELATIVE))
  11547             .expect("remove replica contract");
  11548         let missing_error = load_contract_bundle(&missing_root)
  11549             .expect_err("missing replica contract must fail bundle loading");
  11550         assert!(missing_error.contains(REPLICA_CONTRACT_RELATIVE));
  11551         let _ = fs::remove_dir_all(missing_root);
  11552 
  11553         let unknown_root = create_synthetic_workspace("replica_contract_unknown_field");
  11554         let replica_path = unknown_root.join(REPLICA_CONTRACT_RELATIVE);
  11555         let replica = fs::read_to_string(&replica_path).expect("read replica contract");
  11556         write_file(&replica_path, &format!("{replica}unexpected = true\n"));
  11557         let unknown_error = load_contract_bundle(&unknown_root)
  11558             .expect_err("unknown replica contract field must fail bundle loading");
  11559         assert!(unknown_error.contains(REPLICA_CONTRACT_RELATIVE));
  11560         assert!(unknown_error.contains("unexpected"));
  11561         let _ = fs::remove_dir_all(unknown_root);
  11562     }
  11563 
  11564     #[test]
  11565     fn conformance_vector_mirrors_are_required_even_when_parent_is_deleted() {
  11566         let root = create_synthetic_workspace("required_conformance_mirrors");
  11567         validate_conformance_vector_mirrors(&root).expect("validate synthetic mirrors");
  11568 
  11569         let (_, mirror_relative) = CONFORMANCE_VECTOR_MIRRORS[0];
  11570         let mirror_path = root.join(mirror_relative);
  11571         fs::remove_file(&mirror_path).expect("remove required mirror");
  11572         let missing_file_error = validate_conformance_vector_mirrors(&root)
  11573             .expect_err("missing required mirror file must fail");
  11574         assert!(missing_file_error.contains(&format!("read {mirror_relative}")));
  11575 
  11576         write_file(&mirror_path, SYNTHETIC_CONFORMANCE_VECTOR);
  11577         fs::remove_dir_all(mirror_path.parent().expect("mirror parent"))
  11578             .expect("remove required mirror parent");
  11579         let missing_parent_error = validate_conformance_vector_mirrors(&root)
  11580             .expect_err("missing required mirror parent must fail");
  11581         assert!(missing_parent_error.contains(&format!("read {mirror_relative}")));
  11582 
  11583         let _ = fs::remove_dir_all(root);
  11584     }
  11585 
  11586     #[test]
  11587     fn release_record_and_conformance_mirror_validation_reject_drift() {
  11588         let root = create_synthetic_workspace("release_record_drift");
  11589         let bundle = load_contract_bundle(&root).expect("load synthetic contract");
  11590         validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11591             .expect("validate release record");
  11592 
  11593         let record_path = root.join("contracts/releases/1.0.0.toml");
  11594         let record = fs::read_to_string(&record_path).expect("read release record");
  11595         write_file(
  11596             &record_path,
  11597             &record.replace("status = \"unreleased\"", "status = \"pending\""),
  11598         );
  11599         let status_error = validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11600             .expect_err("unsupported release status must fail");
  11601         assert!(status_error.contains("must be unreleased, released, or yanked"));
  11602 
  11603         write_file(
  11604             &record_path,
  11605             &record.replace(
  11606                 "replica = \"contracts/replica.toml\"",
  11607                 "replica = \"contracts/replica-v1.toml\"",
  11608             ),
  11609         );
  11610         let replica_artifact_error =
  11611             validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11612                 .expect_err("noncanonical replica artifact must fail");
  11613         assert!(replica_artifact_error.contains(
  11614             "release artifact path contracts/replica-v1.toml must use canonical path contracts/replica.toml"
  11615         ));
  11616 
  11617         write_file(
  11618             &record_path,
  11619             &record.replace(
  11620                 "operations = \"contracts/operations.toml\"",
  11621                 "operations = \"contracts/operations-v1.toml\"",
  11622             ),
  11623         );
  11624         let operations_artifact_error =
  11625             validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11626                 .expect_err("noncanonical operations artifact must fail");
  11627         assert!(operations_artifact_error.contains(
  11628             "release artifact path contracts/operations-v1.toml must use canonical path contracts/operations.toml"
  11629         ));
  11630 
  11631         write_file(&record_path, &record);
  11632         let operations_path = root.join("contracts").join("operations.toml");
  11633         let operations = fs::read_to_string(&operations_path).expect("read operations manifest");
  11634         fs::remove_file(&operations_path).expect("remove operations manifest");
  11635         let missing_operations_error =
  11636             validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11637                 .expect_err("missing operations artifact must fail");
  11638         assert!(
  11639             missing_operations_error
  11640                 .contains("release artifact contracts/operations.toml does not exist")
  11641         );
  11642         write_file(&operations_path, &operations);
  11643 
  11644         write_file(
  11645             &record_path,
  11646             &record.replace("id = \"synthetic-major-release\"", "id = \"Bad_Id\""),
  11647         );
  11648         let id_error = validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11649             .expect_err("invalid release change id must fail");
  11650         assert!(id_error.contains("lowercase kebab-case"));
  11651         write_file(&record_path, &record);
  11652 
  11653         write_file(
  11654             &record_path,
  11655             &record.replace(
  11656                 "semver_impacts = [\"breaking\"]",
  11657                 "semver_impacts = [\"fix\"]",
  11658             ),
  11659         );
  11660         let classification_error = validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11661             .expect_err("classification and semver impact mismatch must fail");
  11662         assert!(classification_error.contains("does not match its governed semver impacts"));
  11663 
  11664         write_file(
  11665             &record_path,
  11666             &record.replace(
  11667                 "semver_impacts = [\"breaking\"]",
  11668                 "semver_impacts = [\"unknown-impact\"]",
  11669             ),
  11670         );
  11671         let impact_error = validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11672             .expect_err("unknown semver impact must fail");
  11673         assert!(impact_error.contains("is not governed by contracts/version.toml"));
  11674         write_file(&record_path, &record);
  11675 
  11676         write_file(&root.join(CHANGELOG_RELATIVE), "# Changelog\n");
  11677         let notes_error = validate_release_record(&root, "1.0.0", &bundle.version.semver)
  11678             .expect_err("missing release notes must fail");
  11679         assert!(notes_error.contains("missing heading"));
  11680 
  11681         let (canonical_relative, mirror_relative) = CONFORMANCE_VECTOR_MIRRORS[0];
  11682         write_file(&root.join(canonical_relative), "canonical\n");
  11683         write_file(&root.join(mirror_relative), "drifted\n");
  11684         let mirror_error = validate_conformance_vector_mirrors(&root)
  11685             .expect_err("packaged conformance drift must fail");
  11686         assert!(mirror_error.contains("must exactly match"));
  11687 
  11688         let _ = fs::remove_dir_all(root);
  11689     }
  11690 
  11691     #[test]
  11692     fn calendar_operation_authority_reports_exact_signature_drift() {
  11693         let root = workspace_root();
  11694         let mut bundle = load_contract_bundle(&root).expect("load contract");
  11695         let manifest = &mut bundle.operations_manifest;
  11696         let shared_types =
  11697             collect_non_empty_set(&manifest.shared_types.public, "shared_types.public")
  11698                 .expect("shared public types");
  11699         manifest
  11700             .operations
  11701             .get_mut("social_calendar_date_event_build_authored_draft")
  11702             .expect("calendar authored operation")
  11703             .outputs = vec!["NostrTags".to_string()];
  11704 
  11705         let error = validate_calendar_operation_authority(manifest, &shared_types)
  11706             .expect_err("calendar operation signature drift");
  11707         assert!(error.contains("outputs drift"));
  11708     }
  11709 
  11710     #[test]
  11711     fn calendar_operation_authority_reports_obsolete_operation_drift() {
  11712         let root = workspace_root();
  11713         let mut bundle = load_contract_bundle(&root).expect("load contract");
  11714         let manifest = &mut bundle.operations_manifest;
  11715         let shared_types =
  11716             collect_non_empty_set(&manifest.shared_types.public, "shared_types.public")
  11717                 .expect("shared public types");
  11718         let obsolete = manifest
  11719             .operations
  11720             .remove("social_calendar_date_event_build_authored_draft")
  11721             .expect("calendar authored operation");
  11722         manifest.operations.insert(
  11723             "social_calendar_date_event_build_tags".to_string(),
  11724             obsolete,
  11725         );
  11726 
  11727         let error = validate_calendar_operation_authority(manifest, &shared_types)
  11728             .expect_err("obsolete calendar operation drift");
  11729         assert!(error.contains("calendar operation authority drift"));
  11730         assert!(error.contains("social_calendar_date_event_build_tags"));
  11731     }
  11732 
  11733     #[test]
  11734     fn calendar_operation_authority_reports_obsolete_rsvp_operation_drift() {
  11735         let root = workspace_root();
  11736         let mut bundle = load_contract_bundle(&root).expect("load contract");
  11737         let manifest = &mut bundle.operations_manifest;
  11738         let shared_types =
  11739             collect_non_empty_set(&manifest.shared_types.public, "shared_types.public")
  11740                 .expect("shared public types");
  11741         let obsolete = manifest
  11742             .operations
  11743             .remove("social_calendar_rsvp_build_authored_draft")
  11744             .expect("calendar RSVP authored operation");
  11745         manifest
  11746             .operations
  11747             .insert("social_calendar_rsvp_build_tags".to_string(), obsolete);
  11748 
  11749         let error = validate_calendar_operation_authority(manifest, &shared_types)
  11750             .expect_err("obsolete calendar RSVP operation drift");
  11751         assert!(error.contains("calendar operation authority drift"));
  11752         assert!(error.contains("social_calendar_rsvp_build_tags"));
  11753     }
  11754 
  11755     #[test]
  11756     fn validate_current_canonical_event_boundary() {
  11757         let root = workspace_root();
  11758         validate_canonical_event_boundary(&root).expect("validate canonical event boundary");
  11759     }
  11760 
  11761     #[test]
  11762     fn canonical_event_boundary_reports_row_drift() {
  11763         let root = workspace_root();
  11764         let matrix_path = resolve_event_boundary_matrix_path(&root).expect("matrix path");
  11765         let raw = fs::read_to_string(&matrix_path).expect("read matrix");
  11766         let drifted = raw.replacen(
  11767             "| message | 14 | Message |",
  11768             "| message | 999 | Message |",
  11769             1,
  11770         );
  11771         let temp = temp_root("event_boundary_drift");
  11772         let override_path = temp.join("spec-coverage.md");
  11773         write_file(&override_path, &drifted);
  11774 
  11775         let err = validate_canonical_event_boundary_at_path(&root, &override_path)
  11776             .expect_err("message kind drift should fail");
  11777         assert!(err.contains("message kind drift"));
  11778 
  11779         let _ = fs::remove_dir_all(temp);
  11780     }
  11781 
  11782     #[test]
  11783     fn canonical_event_boundary_rejects_deletion_operation_drift() {
  11784         let root = workspace_root();
  11785         let matrix_path = resolve_event_boundary_matrix_path(&root).expect("matrix path");
  11786         let raw = fs::read_to_string(&matrix_path).expect("read matrix");
  11787         let (preamble, table) = raw
  11788             .split_once("## Coverage matrix")
  11789             .expect("coverage matrix marker");
  11790         let drifted = format!(
  11791             "{preamble}## Coverage matrix{}",
  11792             table.replacen(
  11793                 "social.deletion_request.project_verified_event",
  11794                 "social.deletion_request.project_unverified_event",
  11795                 1,
  11796             )
  11797         );
  11798         let temp = temp_root("deletion_event_boundary_drift");
  11799         let override_path = temp.join("spec-coverage.md");
  11800         write_file(&override_path, &drifted);
  11801 
  11802         let error = validate_canonical_event_boundary_at_path(&root, &override_path)
  11803             .expect_err("deletion operation drift must fail");
  11804         assert!(error.contains("deletion_request rpc drift"), "{error}");
  11805 
  11806         let _ = fs::remove_dir_all(temp);
  11807     }
  11808 
  11809     #[test]
  11810     fn event_boundary_never_falls_back_to_parent_human_documentation() {
  11811         let parent = temp_root("event_boundary_parent_docs");
  11812         let capsule = parent.join("oss/lib");
  11813         fs::create_dir_all(&capsule).expect("capsule root");
  11814         let parent_doc = parent.join(
  11815             "docs/platform/canonical/open_source/radroots_v1_spec/02_public_contract_and_runtime/08_event_boundary_matrix.md",
  11816         );
  11817         write_file(&parent_doc, &synthetic_event_boundary_matrix());
  11818 
  11819         let error = resolve_event_boundary_matrix_path(&capsule)
  11820             .expect_err("parent human documentation must not become contract input");
  11821         assert!(error.contains(EVENT_BOUNDARY_MATRIX_RELATIVE));
  11822         let _ = fs::remove_dir_all(parent);
  11823     }
  11824 
  11825     #[test]
  11826     fn validate_synthetic_operation_contract_bundle() {
  11827         let root = create_synthetic_workspace("operation_contract_bundle");
  11828         add_operation_contract_files(&root);
  11829         let bundle = load_contract_bundle(&root).expect("load contract");
  11830         validate_generic_contract_bundle(&bundle).expect("validate contract");
  11831         let _ = fs::remove_dir_all(root);
  11832     }
  11833 
  11834     #[test]
  11835     fn parses_enum_variants_in_declared_order() {
  11836         let source = r#"
  11837 pub enum UnitDimension {
  11838     Count,
  11839     Mass,
  11840     Volume,
  11841 }
  11842 "#;
  11843         let enum_body = extract_enum_body(source, "UnitDimension").expect("enum body");
  11844         let variants = parse_enum_variants(enum_body);
  11845         assert_eq!(variants, vec!["Count", "Mass", "Volume"]);
  11846     }
  11847 
  11848     #[test]
  11849     fn fails_when_enum_order_does_not_match_contract() {
  11850         let source = r#"
  11851 pub enum UnitDimension {
  11852     Mass,
  11853     Count,
  11854     Volume,
  11855 }
  11856 "#;
  11857         let enum_body = extract_enum_body(source, "UnitDimension").expect("enum body");
  11858         let variants = parse_enum_variants(enum_body);
  11859         let expected = CORE_UNIT_DIMENSION_ORDER
  11860             .iter()
  11861             .map(|item| (*item).to_string())
  11862             .collect::<Vec<_>>();
  11863         assert_ne!(variants, expected);
  11864     }
  11865 
  11866     #[test]
  11867     fn coverage_policy_matches_non_simplex_workspace_crates() {
  11868         let root = workspace_root();
  11869         let expected_names =
  11870             coverage_required_workspace_crates(&root).expect("workspace coverage crates");
  11871         let policy = load_coverage_policy(&root.join("contracts")).expect("coverage policy");
  11872         let required_names = policy
  11873             .required_crates()
  11874             .expect("required crates")
  11875             .into_iter()
  11876             .collect::<BTreeSet<_>>();
  11877         assert_eq!(expected_names, required_names);
  11878         assert!(
  11879             required_names
  11880                 .iter()
  11881                 .all(|crate_name| !coverage_policy_excludes_workspace_crate(crate_name))
  11882         );
  11883     }
  11884 
  11885     #[test]
  11886     fn coverage_required_workspace_crates_excludes_non_policy_packages() {
  11887         let root = temp_root("coverage_required_workspace_simplex");
  11888         write_file(
  11889             &root.join("Cargo.toml"),
  11890             r#"[workspace]
  11891 members = ["crates/a", "crates/radroots_simplex_probe", "crates/simplex_probe"]
  11892 resolver = "2"
  11893 "#,
  11894         );
  11895         write_file(
  11896             &root.join("crates").join("a").join("Cargo.toml"),
  11897             r#"[package]
  11898 name = "radroots_a"
  11899 version = "1.0.0"
  11900 edition = "2024"
  11901 "#,
  11902         );
  11903         write_file(
  11904             &root
  11905                 .join("crates")
  11906                 .join("radroots_simplex_probe")
  11907                 .join("Cargo.toml"),
  11908             r#"[package]
  11909 name = "radroots_simplex_probe"
  11910 version = "1.0.0"
  11911 edition = "2024"
  11912 "#,
  11913         );
  11914         write_file(
  11915             &root.join("crates").join("simplex_probe").join("Cargo.toml"),
  11916             r#"[package]
  11917 name = "simplex_probe"
  11918 version = "1.0.0"
  11919 edition = "2024"
  11920 "#,
  11921         );
  11922 
  11923         let required =
  11924             coverage_required_workspace_crates(&root).expect("workspace coverage crates");
  11925         assert_eq!(
  11926             required,
  11927             ["radroots_a".to_string()]
  11928                 .into_iter()
  11929                 .collect::<BTreeSet<_>>()
  11930         );
  11931         assert!(coverage_policy_excludes_workspace_crate(
  11932             "radroots_simplex_probe"
  11933         ));
  11934         assert!(coverage_policy_excludes_workspace_crate("simplex_probe"));
  11935         assert!(!coverage_policy_excludes_workspace_crate("radroots_a"));
  11936 
  11937         let _ = fs::remove_dir_all(root);
  11938     }
  11939 
  11940     #[test]
  11941     fn coverage_required_crates_match_policy_required_status() {
  11942         let root = workspace_root();
  11943         let contract_root = root.join("contracts");
  11944         let policy = load_coverage_policy(&contract_root).expect("coverage policy");
  11945         let required = CoverageRequiredFile {
  11946             required: CoverageRequiredSection {
  11947                 crates: policy.required_crates().expect("coverage required"),
  11948             },
  11949         };
  11950         let required_names = required
  11951             .required
  11952             .crates
  11953             .into_iter()
  11954             .collect::<BTreeSet<_>>();
  11955         let policy_required = policy
  11956             .required_crates()
  11957             .expect("policy required crates")
  11958             .into_iter()
  11959             .collect::<BTreeSet<_>>();
  11960         assert_eq!(required_names, policy_required);
  11961     }
  11962 
  11963     #[test]
  11964     fn coverage_policy_required_crates_report_policy_errors() {
  11965         let missing_root = temp_root("load_coverage_required_missing_policy");
  11966         let missing_err =
  11967             load_coverage_policy(&missing_root).expect_err("missing policy should fail");
  11968         assert!(missing_err.contains("coverage.toml"));
  11969         let _ = fs::remove_dir_all(&missing_root);
  11970 
  11971         let duplicate_root =
  11972             create_synthetic_workspace("load_coverage_required_duplicate_required");
  11973         let contract_root = duplicate_root.join("contracts");
  11974         let coverage_root = coverage_root(&contract_root);
  11975         write_file(
  11976             &coverage_root.join("coverage.toml"),
  11977             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[required]\ncrates = [\"radroots_a\", \"radroots_a\"]\n",
  11978         );
  11979         let duplicate_err =
  11980             load_coverage_policy(&contract_root).expect_err("duplicate required crates");
  11981         assert!(duplicate_err.contains("duplicate crate"));
  11982         let _ = fs::remove_dir_all(&duplicate_root);
  11983     }
  11984 
  11985     #[test]
  11986     fn package_field_configured_accepts_workspace_table() {
  11987         let mut package = toml::value::Table::new();
  11988         let mut repository = toml::value::Table::new();
  11989         repository.insert("workspace".to_string(), toml::Value::Boolean(true));
  11990         package.insert("repository".to_string(), toml::Value::Table(repository));
  11991         assert!(package_field_configured(&package, "repository"));
  11992     }
  11993 
  11994     #[test]
  11995     fn validate_required_coverage_summary_enforces_required_threshold() {
  11996         let root = temp_root("coverage_summary");
  11997         let coverage_dir = root.join("target").join("coverage");
  11998         fs::create_dir_all(&coverage_dir).expect("create coverage dir");
  11999         fs::write(
  12000             coverage_dir.join("coverage-refresh.tsv"),
  12001             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_core\tpass\t90.0\t90.0\t90.0\t90.0\tfile\n",
  12002         )
  12003         .expect("write coverage file");
  12004         let required = ["radroots_core".to_string()]
  12005             .into_iter()
  12006             .collect::<BTreeSet<_>>();
  12007         validate_required_coverage_summary(&root, &required, required_thresholds())
  12008             .expect("coverage summary");
  12009 
  12010         fs::write(
  12011             coverage_dir.join("coverage-refresh.tsv"),
  12012             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_core\tpass\t90.0\t89.9\t90.0\t90.0\tfile\n",
  12013         )
  12014         .expect("write function coverage file");
  12015         let func_err = validate_required_coverage_summary(&root, &required, required_thresholds())
  12016             .expect_err("function coverage below 90");
  12017         assert!(func_err.contains("must satisfy coverage policy"));
  12018 
  12019         fs::write(
  12020             coverage_dir.join("coverage-refresh.tsv"),
  12021             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_core\tpass\t90.0\t90.0\t89.9\t90.0\tfile\n",
  12022         )
  12023         .expect("write branch coverage file");
  12024         let branch_err =
  12025             validate_required_coverage_summary(&root, &required, required_thresholds())
  12026                 .expect_err("branch coverage below 90");
  12027         assert!(branch_err.contains("must satisfy coverage policy"));
  12028 
  12029         fs::write(
  12030             coverage_dir.join("coverage-refresh.tsv"),
  12031             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_core\tpass\t90.0\t90.0\tunavailable\t90.0\tfile\n",
  12032         )
  12033         .expect("write unavailable branch coverage file");
  12034         let missing_branch_err =
  12035             validate_required_coverage_summary(&root, &required, required_thresholds())
  12036                 .expect_err("branch coverage missing under strict policy");
  12037         assert!(missing_branch_err.contains("unavailable"));
  12038 
  12039         fs::write(
  12040             coverage_dir.join("coverage-refresh.tsv"),
  12041             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_core\tpass\t90.0\t90.0\t90.0\t89.9\tfile\n",
  12042         )
  12043         .expect("write region coverage file");
  12044         let region_err =
  12045             validate_required_coverage_summary(&root, &required, required_thresholds())
  12046                 .expect_err("region coverage below 90");
  12047         assert!(region_err.contains("must satisfy coverage policy"));
  12048         let _ = fs::remove_dir_all(&root);
  12049     }
  12050 
  12051     #[test]
  12052     fn validate_required_coverage_summary_with_policy_honors_scope_override() {
  12053         let root = temp_root("coverage_summary_override");
  12054         write_test_coverage_refresh(
  12055             &root,
  12056             &[
  12057                 TestCoverageRefreshRow {
  12058                     crate_name: "radroots_event_codec",
  12059                     status: "pass",
  12060                     thresholds: CoverageThresholds {
  12061                         fail_under_exec_lines: 100.0,
  12062                         fail_under_functions: 100.0,
  12063                         fail_under_regions: 99.946,
  12064                         fail_under_branches: 100.0,
  12065                         require_branches: true,
  12066                     },
  12067                     exec: 100.0,
  12068                     func: 100.0,
  12069                     branch: Some(100.0),
  12070                     region: 99.946385,
  12071                     report_pass: true,
  12072                 },
  12073                 TestCoverageRefreshRow {
  12074                     crate_name: "radroots_log",
  12075                     status: "pass",
  12076                     thresholds: coverage_thresholds(100.0, false),
  12077                     exec: 100.0,
  12078                     func: 100.0,
  12079                     branch: None,
  12080                     region: 100.0,
  12081                     report_pass: true,
  12082                 },
  12083             ],
  12084         );
  12085         let policy_dir = root.join("contracts");
  12086         fs::create_dir_all(&policy_dir).expect("create policy dir");
  12087         fs::write(
  12088             policy_dir.join("coverage.toml"),
  12089             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[overrides.radroots_event_codec]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 99.946\nfail_under_branches = 100.0\ntemporary = true\nreason = \"publish 0.1.0-alpha temporary coverage override\"\n\n[overrides.radroots_log]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = false\ntemporary = true\nreason = \"branch coverage is not applicable while the crate has no measured branch records\"\n\n[required]\ncrates = [\"radroots_event_codec\", \"radroots_log\"]\n",
  12090         )
  12091         .expect("write coverage policy");
  12092         let required = [
  12093             "radroots_event_codec".to_string(),
  12094             "radroots_log".to_string(),
  12095         ]
  12096         .into_iter()
  12097         .collect::<BTreeSet<_>>();
  12098         let policy = read_coverage_policy(&policy_dir.join("coverage.toml"))
  12099             .expect("parse override coverage policy");
  12100         validate_required_coverage_summary_with_policy(&root, &required, &policy)
  12101             .expect("coverage summary should honor override");
  12102         let _ = fs::remove_dir_all(&root);
  12103     }
  12104 
  12105     #[test]
  12106     fn validate_required_coverage_summary_with_policy_rejects_synthetic_report_path() {
  12107         let root = temp_root("coverage_summary_synthetic_report_path");
  12108         write_file(
  12109             &root
  12110                 .join("target")
  12111                 .join("coverage")
  12112                 .join("coverage-refresh.tsv"),
  12113             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100.0\t100.0\t100.0\t100.0\tfile\n",
  12114         );
  12115         let required = ["radroots_a".to_string()]
  12116             .into_iter()
  12117             .collect::<BTreeSet<_>>();
  12118         let policy_dir = root.join("contracts");
  12119         write_file(
  12120             &policy_dir.join("coverage.toml"),
  12121             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[required]\ncrates = [\"radroots_a\"]\n",
  12122         );
  12123         let policy =
  12124             read_coverage_policy(&policy_dir.join("coverage.toml")).expect("parse coverage policy");
  12125         let err = validate_required_coverage_summary_with_policy(&root, &required, &policy)
  12126             .expect_err("synthetic report path should fail");
  12127         assert!(err.contains("coverage gate report"));
  12128         let _ = fs::remove_dir_all(&root);
  12129     }
  12130 
  12131     #[test]
  12132     fn validate_required_coverage_summary_with_policy_rejects_stale_gate_report_thresholds() {
  12133         let root = temp_root("coverage_summary_stale_gate_report_thresholds");
  12134         let row = TestCoverageRefreshRow {
  12135             crate_name: "radroots_a",
  12136             status: "pass",
  12137             thresholds: coverage_thresholds(90.0, true),
  12138             exec: 100.0,
  12139             func: 100.0,
  12140             branch: Some(100.0),
  12141             region: 100.0,
  12142             report_pass: true,
  12143         };
  12144         write_test_coverage_refresh(&root, &[row]);
  12145         let required = ["radroots_a".to_string()]
  12146             .into_iter()
  12147             .collect::<BTreeSet<_>>();
  12148         let policy_dir = root.join("contracts");
  12149         write_file(
  12150             &policy_dir.join("coverage.toml"),
  12151             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[required]\ncrates = [\"radroots_a\"]\n",
  12152         );
  12153         let policy =
  12154             read_coverage_policy(&policy_dir.join("coverage.toml")).expect("parse coverage policy");
  12155         let err = validate_required_coverage_summary_with_policy(&root, &required, &policy)
  12156             .expect_err("stale threshold report should fail");
  12157         assert!(err.contains("thresholds do not match policy"));
  12158         let _ = fs::remove_dir_all(&root);
  12159     }
  12160 
  12161     #[test]
  12162     fn validate_required_coverage_summary_with_policy_rejects_row_report_mismatch() {
  12163         let root = temp_root("coverage_summary_row_report_mismatch");
  12164         let row = TestCoverageRefreshRow {
  12165             crate_name: "radroots_a",
  12166             status: "pass",
  12167             thresholds: coverage_thresholds(100.0, true),
  12168             exec: 99.0,
  12169             func: 100.0,
  12170             branch: Some(100.0),
  12171             region: 100.0,
  12172             report_pass: true,
  12173         };
  12174         let report_relative = write_test_coverage_gate_report(&root, &row);
  12175         write_file(
  12176             &root
  12177                 .join("target")
  12178                 .join("coverage")
  12179                 .join("coverage-refresh.tsv"),
  12180             &format!(
  12181                 "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100.0\t100.0\t100.0\t100.0\t{report_relative}\n"
  12182             ),
  12183         );
  12184         let required = ["radroots_a".to_string()]
  12185             .into_iter()
  12186             .collect::<BTreeSet<_>>();
  12187         let policy_dir = root.join("contracts");
  12188         write_file(
  12189             &policy_dir.join("coverage.toml"),
  12190             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[required]\ncrates = [\"radroots_a\"]\n",
  12191         );
  12192         let policy =
  12193             read_coverage_policy(&policy_dir.join("coverage.toml")).expect("parse coverage policy");
  12194         let err = validate_required_coverage_summary_with_policy(&root, &required, &policy)
  12195             .expect_err("row and report mismatch should fail");
  12196         assert!(err.contains("does not match coverage gate report"));
  12197         let _ = fs::remove_dir_all(&root);
  12198     }
  12199 
  12200     #[test]
  12201     fn validate_publish_package_metadata_requires_description() {
  12202         let root = temp_root("publish_metadata");
  12203         fs::create_dir_all(root.join("crates").join("a")).expect("create crate dir");
  12204         fs::write(
  12205             root.join("Cargo.toml"),
  12206             r#"[workspace]
  12207 members = ["crates/a"]
  12208 "#,
  12209         )
  12210         .expect("write workspace manifest");
  12211         fs::write(
  12212             root.join("crates").join("a").join("Cargo.toml"),
  12213             r#"[package]
  12214 name = "radroots_a"
  12215 version = "1.0.0"
  12216 edition = "2024"
  12217 repository = { workspace = true }
  12218 homepage = { workspace = true }
  12219 documentation = "https://docs.rs/radroots_a"
  12220 readme = { workspace = true }
  12221 "#,
  12222         )
  12223         .expect("write package manifest");
  12224         let publish = ["radroots_a".to_string()]
  12225             .into_iter()
  12226             .collect::<BTreeSet<_>>();
  12227         let err =
  12228             validate_publish_package_metadata(&root, &publish).expect_err("missing description");
  12229         assert!(err.contains("package.description"));
  12230         let _ = fs::remove_dir_all(&root);
  12231     }
  12232 
  12233     #[test]
  12234     fn synthetic_workspace_validates_contract_and_release_preflight() {
  12235         let root = create_synthetic_workspace("synthetic_valid");
  12236         let bundle = load_contract_bundle(&root).expect("load synthetic bundle");
  12237         validate_generic_contract_bundle(&bundle).expect("validate synthetic bundle");
  12238         validate_generic_release_preflight(&root).expect("validate synthetic preflight");
  12239         let _ = fs::remove_dir_all(root);
  12240     }
  12241 
  12242     #[test]
  12243     fn helper_functions_cover_error_paths() {
  12244         let empty = collect_unique_set(&["".to_string()], "field").expect_err("empty value");
  12245         assert!(empty.contains("field contains an empty crate name"));
  12246         let duplicate = collect_unique_set(&["a".to_string(), "a".to_string()], "field")
  12247             .expect_err("duplicate value");
  12248         assert!(duplicate.contains("field has duplicate crate a"));
  12249 
  12250         let values = ["b".to_string(), "a".to_string()];
  12251         let set = collect_unique_set(&values, "field").expect("unique values");
  12252         assert_eq!(join_set(&set), "a, b".to_string());
  12253 
  12254         assert!(package_publish_enabled(None));
  12255         assert!(package_publish_enabled(Some(&PackagePublish::Bool(true))));
  12256         assert!(!package_publish_enabled(Some(&PackagePublish::Bool(false))));
  12257         assert!(package_publish_enabled(Some(&PackagePublish::Registries(
  12258             vec!["crates-io".to_string(),]
  12259         ))));
  12260         assert!(!package_publish_enabled(Some(&PackagePublish::Registries(
  12261             Vec::new()
  12262         ))));
  12263 
  12264         let mut package = toml::value::Table::new();
  12265         package.insert("description".to_string(), toml::Value::Integer(42));
  12266         assert!(!package_field_configured(&package, "description"));
  12267 
  12268         assert!(!publish_config_is_public(None));
  12269         assert!(!publish_config_is_public(Some(&PackagePublish::Bool(true))));
  12270         assert!(publish_config_is_public(Some(&PackagePublish::Registries(
  12271             vec!["crates-io".to_string(),]
  12272         ))));
  12273         assert!(!publish_config_is_public(Some(
  12274             &PackagePublish::Registries(vec!["crates-io".to_string(), "mirror".to_string(),])
  12275         )));
  12276         assert!(!publish_config_is_public(Some(
  12277             &PackagePublish::Registries(vec!["mirror".to_string(),])
  12278         )));
  12279 
  12280         assert!(!publish_config_is_non_public(None));
  12281         assert!(!publish_config_is_non_public(Some(&PackagePublish::Bool(
  12282             true
  12283         ))));
  12284         assert!(publish_config_is_non_public(Some(&PackagePublish::Bool(
  12285             false
  12286         ))));
  12287         assert!(!publish_config_is_non_public(Some(
  12288             &PackagePublish::Registries(vec!["crates-io".to_string(),])
  12289         )));
  12290     }
  12291 
  12292     #[test]
  12293     fn release_contract_helpers_cover_classification_and_env_override_paths() {
  12294         let release = ReleaseSection {
  12295             version: "1.0.0".to_string(),
  12296         };
  12297         let empty_order = ReleaseCrateSet { crates: Vec::new() };
  12298 
  12299         let legacy = ReleaseContractFile {
  12300             release: ReleaseSection {
  12301                 version: release.version.clone(),
  12302             },
  12303             publication: None,
  12304             workspace_classification: None,
  12305             classification: ReleaseClassification::default(),
  12306             publish: Some(ReleaseCrateSet {
  12307                 crates: vec!["radroots_public".to_string()],
  12308             }),
  12309             internal: Some(ReleaseCrateSet {
  12310                 crates: vec!["radroots_internal".to_string()],
  12311             }),
  12312             publish_order: ReleaseCrateSet {
  12313                 crates: empty_order.crates.clone(),
  12314             },
  12315         };
  12316         assert!(!legacy.uses_classification());
  12317         assert_eq!(legacy.public_crates(), vec!["radroots_public".to_string()]);
  12318         assert_eq!(
  12319             legacy.internal_crates(),
  12320             vec!["radroots_internal".to_string()]
  12321         );
  12322 
  12323         let empty_legacy = ReleaseContractFile {
  12324             release: ReleaseSection {
  12325                 version: release.version.clone(),
  12326             },
  12327             publication: None,
  12328             workspace_classification: None,
  12329             classification: ReleaseClassification::default(),
  12330             publish: None,
  12331             internal: None,
  12332             publish_order: ReleaseCrateSet {
  12333                 crates: empty_order.crates.clone(),
  12334             },
  12335         };
  12336         assert!(!empty_legacy.uses_classification());
  12337         assert_eq!(empty_legacy.public_crates(), Vec::<String>::new());
  12338         assert_eq!(empty_legacy.internal_crates(), Vec::<String>::new());
  12339 
  12340         let internal = ReleaseContractFile {
  12341             release: ReleaseSection {
  12342                 version: release.version.clone(),
  12343             },
  12344             publication: None,
  12345             workspace_classification: None,
  12346             classification: ReleaseClassification {
  12347                 internal: vec!["radroots_internal_only".to_string()],
  12348                 ..ReleaseClassification::default()
  12349             },
  12350             publish: None,
  12351             internal: None,
  12352             publish_order: ReleaseCrateSet {
  12353                 crates: empty_order.crates.clone(),
  12354             },
  12355         };
  12356         assert!(internal.uses_classification());
  12357 
  12358         let deferred = ReleaseContractFile {
  12359             release: ReleaseSection {
  12360                 version: release.version.clone(),
  12361             },
  12362             publication: None,
  12363             workspace_classification: None,
  12364             classification: ReleaseClassification {
  12365                 deferred: vec!["radroots_deferred".to_string()],
  12366                 ..ReleaseClassification::default()
  12367             },
  12368             publish: None,
  12369             internal: None,
  12370             publish_order: ReleaseCrateSet {
  12371                 crates: empty_order.crates.clone(),
  12372             },
  12373         };
  12374         assert!(deferred.uses_classification());
  12375         assert_eq!(
  12376             deferred.deferred_crates(),
  12377             vec!["radroots_deferred".to_string()]
  12378         );
  12379 
  12380         let retired = ReleaseContractFile {
  12381             release: ReleaseSection {
  12382                 version: release.version.clone(),
  12383             },
  12384             publication: None,
  12385             workspace_classification: None,
  12386             classification: ReleaseClassification {
  12387                 retired: vec!["radroots_retired".to_string()],
  12388                 ..ReleaseClassification::default()
  12389             },
  12390             publish: None,
  12391             internal: None,
  12392             publish_order: ReleaseCrateSet {
  12393                 crates: empty_order.crates.clone(),
  12394             },
  12395         };
  12396         assert!(retired.uses_classification());
  12397         assert_eq!(
  12398             retired.retired_crates(),
  12399             vec!["radroots_retired".to_string()]
  12400         );
  12401 
  12402         let yank_only = ReleaseContractFile {
  12403             release,
  12404             publication: None,
  12405             workspace_classification: None,
  12406             classification: ReleaseClassification {
  12407                 yank_only: vec!["radroots_yank_only".to_string()],
  12408                 ..ReleaseClassification::default()
  12409             },
  12410             publish: None,
  12411             internal: None,
  12412             publish_order: empty_order,
  12413         };
  12414         assert!(yank_only.uses_classification());
  12415         assert_eq!(
  12416             yank_only.yank_only_crates(),
  12417             vec!["radroots_yank_only".to_string()]
  12418         );
  12419 
  12420         let root = create_synthetic_workspace("release_contract_env_override");
  12421         let policy_path = root_release_policy_path(&root);
  12422         let resolved =
  12423             resolve_release_contract_path_with_override(&root, "1.0.0", Some(policy_path.clone()))
  12424                 .expect("existing override policy should resolve");
  12425         assert_eq!(resolved, policy_path);
  12426 
  12427         let missing_policy = root.join("missing-release-policy.toml");
  12428         let err = resolve_release_contract_path_with_override(
  12429             &root,
  12430             "1.0.0",
  12431             Some(missing_policy.clone()),
  12432         )
  12433         .expect_err("missing fixture policy should fail");
  12434         assert!(err.contains("release policy override points to a missing file"));
  12435         assert!(err.contains(&missing_policy.display().to_string()));
  12436 
  12437         let _ = fs::remove_dir_all(&root);
  12438     }
  12439 
  12440     #[test]
  12441     fn workspace_package_manifests_reject_duplicate_package_names() {
  12442         let root = temp_root("workspace_manifest_duplicates");
  12443         write_file(
  12444             &root.join("Cargo.toml"),
  12445             r#"[workspace]
  12446 members = ["crates/a", "crates/b"]
  12447 "#,
  12448         );
  12449         let package_manifest =
  12450             "[package]\nname = \"duplicate\"\nversion = \"0.1.0\"\nedition = \"2024\"\n";
  12451         write_file(
  12452             &root.join("crates").join("a").join("Cargo.toml"),
  12453             package_manifest,
  12454         );
  12455         write_file(
  12456             &root.join("crates").join("b").join("Cargo.toml"),
  12457             package_manifest,
  12458         );
  12459         let err = workspace_package_manifests(&root)
  12460             .expect_err("duplicate package names in manifest map");
  12461         assert!(err.contains("duplicate workspace package name in manifest map"));
  12462         let _ = fs::remove_dir_all(root);
  12463     }
  12464 
  12465     #[test]
  12466     fn coverage_refresh_parsing_and_summary_errors_are_reported() {
  12467         let root = temp_root("coverage_refresh_errors");
  12468         let coverage_dir = root.join("target").join("coverage");
  12469         fs::create_dir_all(&coverage_dir).expect("create coverage dir");
  12470 
  12471         write_file(
  12472             &coverage_dir.join("coverage-refresh.tsv"),
  12473             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nbad-row\n",
  12474         );
  12475         let bad_row = load_coverage_refresh_rows(&root).expect_err("invalid coverage row");
  12476         assert!(bad_row.contains("at least 7 columns"));
  12477 
  12478         write_file(
  12479             &coverage_dir.join("coverage-refresh.tsv"),
  12480             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\tnot-a-number\t100\t100\t100\tfile\n",
  12481         );
  12482         let bad_percent = load_coverage_refresh_rows(&root).expect_err("invalid coverage percent");
  12483         assert!(bad_percent.contains("parse exec"));
  12484 
  12485         write_file(
  12486             &coverage_dir.join("coverage-refresh.tsv"),
  12487             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100\t100\t100\tnot-a-number\tfile\n",
  12488         );
  12489         let bad_region =
  12490             load_coverage_refresh_rows(&root).expect_err("invalid region coverage percent");
  12491         assert!(bad_region.contains("parse region"));
  12492 
  12493         write_file(
  12494             &coverage_dir.join("coverage-refresh.tsv"),
  12495             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100\t100\t100\t100\tfile\nradroots_a\tpass\t100\t100\t100\t100\tfile\n",
  12496         );
  12497         let duplicate_row = load_coverage_refresh_rows(&root).expect_err("duplicate coverage row");
  12498         assert!(duplicate_row.contains("duplicate coverage row"));
  12499 
  12500         write_file(
  12501             &coverage_dir.join("coverage-refresh.tsv"),
  12502             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tfail\t100\t100\t100\t100\tfile\n",
  12503         );
  12504         let required = ["radroots_a".to_string()]
  12505             .into_iter()
  12506             .collect::<BTreeSet<_>>();
  12507         let non_pass = validate_required_coverage_summary(&root, &required, required_thresholds())
  12508             .expect_err("non-pass status");
  12509         assert!(non_pass.contains("non-pass status"));
  12510 
  12511         write_file(
  12512             &coverage_dir.join("coverage-refresh.tsv"),
  12513             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t89.9\t90\t90\t90\tfile\n",
  12514         );
  12515         let below_90 = validate_required_coverage_summary(&root, &required, required_thresholds())
  12516             .expect_err("coverage below 90");
  12517         assert!(below_90.contains("must satisfy coverage policy"));
  12518 
  12519         let missing = ["missing".to_string()].into_iter().collect::<BTreeSet<_>>();
  12520         let missing_err =
  12521             validate_required_coverage_summary(&root, &missing, required_thresholds())
  12522                 .expect_err("missing required row");
  12523         assert!(missing_err.contains("missing from coverage-refresh.tsv"));
  12524 
  12525         let _ = fs::remove_dir_all(root);
  12526     }
  12527 
  12528     #[test]
  12529     fn enum_extract_and_parse_error_paths_are_reported() {
  12530         let missing =
  12531             extract_enum_body("pub struct X;", "UnitDimension").expect_err("missing enum");
  12532         assert!(missing.contains("missing enum"));
  12533 
  12534         let missing_brace = extract_enum_body("pub enum UnitDimension", "UnitDimension")
  12535             .expect_err("missing opening brace");
  12536         assert!(missing_brace.contains("missing opening brace"));
  12537 
  12538         let missing_close =
  12539             extract_enum_body("pub enum UnitDimension { Count, Mass", "UnitDimension")
  12540                 .expect_err("missing closing brace");
  12541         assert!(missing_close.contains("missing closing brace"));
  12542 
  12543         let variants = parse_enum_variants(
  12544             r#"
  12545             ,
  12546             = 1,
  12547             // skip
  12548             #![cfg(test)]
  12549             Count,
  12550             "#,
  12551         );
  12552         assert_eq!(variants, vec!["Count".to_string()]);
  12553 
  12554         let nested = extract_enum_body(
  12555             "pub enum UnitDimension { Count = { 1 }, Mass = 2 }",
  12556             "UnitDimension",
  12557         )
  12558         .expect("nested braces in enum body");
  12559         assert!(nested.contains("Count"));
  12560     }
  12561 
  12562     #[test]
  12563     fn coverage_policy_parity_reports_contract_errors() {
  12564         let root = create_synthetic_workspace("coverage_policy_errors");
  12565         let contract_root = root.join("contracts");
  12566         let coverage_root = coverage_root(&contract_root);
  12567 
  12568         write_file(
  12569             &coverage_root.join("coverage.toml"),
  12570             r#"[gate]
  12571 fail_under_exec_lines = 90.0
  12572 fail_under_functions = 90.0
  12573 fail_under_regions = 90.0
  12574 fail_under_branches = 90.0
  12575 require_branches = true
  12576 
  12577 [required]
  12578 crates = []
  12579 "#,
  12580         );
  12581         let empty_required =
  12582             validate_coverage_policy_parity(&root, &contract_root).expect_err("empty required");
  12583         assert!(empty_required.contains("required crates list must not be empty"));
  12584 
  12585         write_file(
  12586             &coverage_root.join("coverage.toml"),
  12587             r#"[gate]
  12588 fail_under_exec_lines = 89.0
  12589 fail_under_functions = 90.0
  12590 fail_under_regions = 90.0
  12591 fail_under_branches = 90.0
  12592 require_branches = true
  12593 
  12594 [required]
  12595 crates = ["radroots_a", "radroots_b"]
  12596 "#,
  12597         );
  12598         let invalid_gate = validate_coverage_policy_parity(&root, &contract_root)
  12599             .expect_err("invalid policy thresholds");
  12600         assert!(invalid_gate.contains("90/90/90/90"));
  12601 
  12602         write_file(
  12603             &coverage_root.join("coverage.toml"),
  12604             r#"[gate]
  12605 fail_under_exec_lines = 90.0
  12606 fail_under_functions = 89.0
  12607 fail_under_regions = 90.0
  12608 fail_under_branches = 90.0
  12609 require_branches = true
  12610 
  12611 [required]
  12612 crates = ["radroots_a", "radroots_b"]
  12613 "#,
  12614         );
  12615         let invalid_functions = validate_coverage_policy_parity(&root, &contract_root)
  12616             .expect_err("invalid function threshold");
  12617         assert!(invalid_functions.contains("90/90/90/90"));
  12618 
  12619         write_file(
  12620             &coverage_root.join("coverage.toml"),
  12621             r#"[gate]
  12622 fail_under_exec_lines = 90.0
  12623 fail_under_functions = 90.0
  12624 fail_under_regions = 89.0
  12625 fail_under_branches = 90.0
  12626 require_branches = true
  12627 
  12628 [required]
  12629 crates = ["radroots_a", "radroots_b"]
  12630 "#,
  12631         );
  12632         let invalid_regions = validate_coverage_policy_parity(&root, &contract_root)
  12633             .expect_err("invalid region threshold");
  12634         assert!(invalid_regions.contains("90/90/90/90"));
  12635 
  12636         write_file(
  12637             &coverage_root.join("coverage.toml"),
  12638             r#"[gate]
  12639 fail_under_exec_lines = 90.0
  12640 fail_under_functions = 90.0
  12641 fail_under_regions = 90.0
  12642 fail_under_branches = 89.0
  12643 require_branches = true
  12644 
  12645 [required]
  12646 crates = ["radroots_a", "radroots_b"]
  12647 "#,
  12648         );
  12649         let invalid_branches = validate_coverage_policy_parity(&root, &contract_root)
  12650             .expect_err("invalid branch threshold");
  12651         assert!(invalid_branches.contains("90/90/90/90"));
  12652 
  12653         write_file(
  12654             &coverage_root.join("coverage.toml"),
  12655             r#"[gate]
  12656 fail_under_exec_lines = 90.0
  12657 fail_under_functions = 90.0
  12658 fail_under_regions = 90.0
  12659 fail_under_branches = 90.0
  12660 require_branches = true
  12661 
  12662 [required]
  12663 crates = ["radroots_a", "radroots_a"]
  12664 "#,
  12665         );
  12666         let duplicate_required = validate_coverage_policy_parity(&root, &contract_root)
  12667             .expect_err("duplicate required crate");
  12668         assert!(duplicate_required.contains("duplicate crate"));
  12669 
  12670         write_file(
  12671             &coverage_root.join("coverage.toml"),
  12672             r#"[gate]
  12673 fail_under_exec_lines = 90.0
  12674 fail_under_functions = 90.0
  12675 fail_under_regions = 90.0
  12676 fail_under_branches = 90.0
  12677 require_branches = false
  12678 
  12679 [required]
  12680 crates = ["radroots_a", "radroots_b"]
  12681 "#,
  12682         );
  12683         let branches_optional = validate_coverage_policy_parity(&root, &contract_root)
  12684             .expect_err("branches must be required");
  12685         assert!(branches_optional.contains("required branches"));
  12686 
  12687         write_file(
  12688             &coverage_root.join("coverage.toml"),
  12689             r#"[gate]
  12690 fail_under_exec_lines = 90.0
  12691 fail_under_functions = 90.0
  12692 fail_under_regions = 90.0
  12693 fail_under_branches = 90.0
  12694 require_branches = true
  12695 
  12696 [overrides.radroots_a]
  12697 fail_under_exec_lines = 89.9
  12698 temporary = true
  12699 reason = "invalid override below the active development baseline"
  12700 
  12701 [required]
  12702 crates = ["radroots_a", "radroots_b"]
  12703 "#,
  12704         );
  12705         let below_minimum_override = validate_coverage_policy_parity(&root, &contract_root)
  12706             .expect_err("numeric override below the active baseline");
  12707         assert!(below_minimum_override.contains("scope radroots_a"));
  12708         assert!(below_minimum_override.contains("at least 90/90/90/90"));
  12709 
  12710         write_file(
  12711             &coverage_root.join("coverage.toml"),
  12712             r#"[gate]
  12713 fail_under_exec_lines = 90.0
  12714 fail_under_functions = 90.0
  12715 fail_under_regions = 90.0
  12716 fail_under_branches = 90.0
  12717 require_branches = true
  12718 
  12719 [required]
  12720 crates = ["radroots_b"]
  12721 "#,
  12722         );
  12723         let missing_workspace = validate_coverage_policy_parity(&root, &contract_root)
  12724             .expect_err("missing workspace crate in policy");
  12725         assert!(missing_workspace.contains("missing workspace crates"));
  12726 
  12727         write_file(
  12728             &coverage_root.join("coverage.toml"),
  12729             r#"[gate]
  12730 fail_under_exec_lines = 90.0
  12731 fail_under_functions = 90.0
  12732 fail_under_regions = 90.0
  12733 fail_under_branches = 90.0
  12734 require_branches = true
  12735 
  12736 [required]
  12737 crates = ["unknown"]
  12738 "#,
  12739         );
  12740         let required_unknown = validate_coverage_policy_parity(&root, &contract_root)
  12741             .expect_err("unknown required crate");
  12742         assert!(required_unknown.contains("includes excluded or unknown crates"));
  12743 
  12744         let _ = fs::remove_dir_all(root);
  12745     }
  12746 
  12747     #[test]
  12748     fn release_publish_policy_reports_contract_errors() {
  12749         let root = create_synthetic_workspace("release_policy_errors");
  12750         let contract_root = root.join("contracts");
  12751         let release_policy_path = root_release_policy_path(&root);
  12752 
  12753         write_file(
  12754             &release_policy_path,
  12755             r#"[release]
  12756 version = ""
  12757 
  12758 [publish]
  12759 crates = ["radroots_a"]
  12760 
  12761 [internal]
  12762 crates = ["radroots_b"]
  12763 
  12764 [publish_order]
  12765 crates = ["radroots_a"]
  12766 "#,
  12767         );
  12768         let empty_version = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12769             .expect_err("empty release version");
  12770         assert!(empty_version.contains("must not be empty"));
  12771 
  12772         write_file(
  12773             &release_policy_path,
  12774             r#"[release]
  12775 version = "2.0.0"
  12776 
  12777 [publish]
  12778 crates = ["radroots_a"]
  12779 
  12780 [internal]
  12781 crates = ["radroots_b"]
  12782 
  12783 [publish_order]
  12784 crates = ["radroots_a"]
  12785 "#,
  12786         );
  12787         let version_mismatch = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12788             .expect_err("release version mismatch");
  12789         assert!(version_mismatch.contains("must match contract version"));
  12790 
  12791         write_file(
  12792             &release_policy_path,
  12793             r#"[release]
  12794 version = "1.0.0"
  12795 
  12796 [publish]
  12797 crates = ["radroots_a"]
  12798 
  12799 [internal]
  12800 crates = ["radroots_a"]
  12801 
  12802 [publish_order]
  12803 crates = ["radroots_a"]
  12804 "#,
  12805         );
  12806         let overlap = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12807             .expect_err("publish/internal overlap");
  12808         assert!(overlap.contains("overlap is not allowed"));
  12809 
  12810         write_file(
  12811             &release_policy_path,
  12812             r#"[release]
  12813 version = "1.0.0"
  12814 
  12815 [publish]
  12816 crates = ["radroots_a"]
  12817 
  12818 [internal]
  12819 crates = []
  12820 
  12821 [publish_order]
  12822 crates = ["radroots_a"]
  12823 "#,
  12824         );
  12825         let missing_workspace = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12826             .expect_err("missing workspace crate");
  12827         assert!(missing_workspace.contains("missing workspace crates"));
  12828 
  12829         write_file(
  12830             &release_policy_path,
  12831             r#"[release]
  12832 version = "1.0.0"
  12833 
  12834 [publish]
  12835 crates = ["radroots_a"]
  12836 
  12837 [internal]
  12838 crates = ["radroots_b"]
  12839 
  12840 [publish_order]
  12841 crates = []
  12842 "#,
  12843         );
  12844         let missing_publish_order = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12845             .expect_err("missing publish order entries");
  12846         assert!(missing_publish_order.contains("missing publish crates"));
  12847 
  12848         write_file(
  12849             &release_policy_path,
  12850             r#"[release]
  12851 version = "1.0.0"
  12852 
  12853 [publish]
  12854 crates = ["radroots_a"]
  12855 
  12856 [internal]
  12857 crates = ["radroots_b"]
  12858 
  12859 [publish_order]
  12860 crates = ["radroots_a", "radroots_b"]
  12861 "#,
  12862         );
  12863         let extra_publish_order = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12864             .expect_err("extra publish order entries");
  12865         assert!(extra_publish_order.contains("non-publish crates"));
  12866 
  12867         write_file(
  12868             &root.join("crates").join("a").join("Cargo.toml"),
  12869             r#"[package]
  12870 name = "radroots_a"
  12871 publish = ["crates-io"]
  12872 version = "1.0.0"
  12873 edition = "2024"
  12874 authors = ["Radroots Test"]
  12875 rust-version = "1.97"
  12876 license = "MIT OR Apache-2.0"
  12877 description = "crate a"
  12878 repository = "https://example.com/a"
  12879 homepage = "https://example.com/a"
  12880 documentation = "https://docs.rs/radroots_a"
  12881 readme = "README.md"
  12882 keywords = ["radroots"]
  12883 categories = ["data-structures"]
  12884 include = ["src/**", "tests/**", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
  12885 
  12886 [package.metadata.docs.rs]
  12887 features = []
  12888 
  12889 [dependencies]
  12890 radroots_b = { path = "../b" }
  12891 "#,
  12892         );
  12893         write_file(
  12894             &root.join("crates").join("b").join("Cargo.toml"),
  12895             r#"[package]
  12896 name = "radroots_b"
  12897 version = "1.0.0"
  12898 edition = "2024"
  12899 description = "crate b"
  12900 repository = "https://example.com/b"
  12901 homepage = "https://example.com/b"
  12902 documentation = "https://docs.example.com/b"
  12903 readme = "README"
  12904 "#,
  12905         );
  12906         write_file(
  12907             &release_policy_path,
  12908             r#"[release]
  12909 version = "1.0.0"
  12910 
  12911 [publish]
  12912 crates = ["radroots_a", "radroots_b"]
  12913 
  12914 [internal]
  12915 crates = []
  12916 
  12917 [publish_order]
  12918 crates = ["radroots_a", "radroots_b"]
  12919 "#,
  12920         );
  12921         let dependency_order = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12922             .expect_err("dependency order violation");
  12923         assert!(dependency_order.contains("must place dependency"));
  12924 
  12925         write_file(
  12926             &release_policy_path,
  12927             r#"[release]
  12928 version = "1.0.0"
  12929 
  12930 [publish]
  12931 crates = ["radroots_a"]
  12932 
  12933 [internal]
  12934 crates = ["radroots_b"]
  12935 
  12936 [publish_order]
  12937 crates = ["radroots_a"]
  12938 "#,
  12939         );
  12940         write_file(
  12941             &root.join("crates").join("b").join("Cargo.toml"),
  12942             r#"[package]
  12943 name = "radroots_b"
  12944 version = "1.0.0"
  12945 edition = "2024"
  12946 publish = false
  12947 "#,
  12948         );
  12949         validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12950             .expect("internal dependency should be ignored in publish ordering");
  12951 
  12952         write_file(
  12953             &root.join("crates").join("a").join("Cargo.toml"),
  12954             r#"[package]
  12955 name = "radroots_a"
  12956 version = "1.0.0"
  12957 edition = "2024"
  12958 publish = false
  12959 "#,
  12960         );
  12961         write_file(
  12962             &release_policy_path,
  12963             r#"[release]
  12964 version = "1.0.0"
  12965 
  12966 [publish]
  12967 crates = ["radroots_a"]
  12968 
  12969 [internal]
  12970 crates = ["radroots_b"]
  12971 
  12972 [publish_order]
  12973 crates = ["radroots_a"]
  12974 "#,
  12975         );
  12976         let publish_flag = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  12977             .expect_err("publish crate must be publishable");
  12978         assert!(publish_flag.contains("must set publish = [\"crates-io\"]"));
  12979 
  12980         write_file(
  12981             &root.join("crates").join("a").join("Cargo.toml"),
  12982             r#"[package]
  12983 name = "radroots_a"
  12984 publish = ["crates-io"]
  12985 version = "1.0.0"
  12986 edition = "2024"
  12987 description = "crate a"
  12988 repository = "https://example.com/a"
  12989 homepage = "https://example.com/a"
  12990 documentation = "https://docs.example.com/a"
  12991 readme = "README"
  12992 "#,
  12993         );
  12994         write_file(
  12995             &root.join("crates").join("b").join("Cargo.toml"),
  12996             r#"[package]
  12997 name = "radroots_b"
  12998 version = "1.0.0"
  12999 edition = "2024"
  13000 "#,
  13001         );
  13002         let internal_flag = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13003             .expect_err("internal crate must be non-publishable");
  13004         assert!(internal_flag.contains("non-public crate"));
  13005 
  13006         let _ = fs::remove_dir_all(root);
  13007     }
  13008 
  13009     #[test]
  13010     fn publication_freeze_requires_every_workspace_package_to_be_private() {
  13011         let root = create_synthetic_workspace("publication_freeze");
  13012         let contract_root = root.join("contracts");
  13013         let release_policy_path = root_release_policy_path(&root);
  13014         write_file(
  13015             &root.join("crates").join("a").join("Cargo.toml"),
  13016             r#"[package]
  13017 name = "radroots_a"
  13018 version = "1.0.0"
  13019 edition = "2024"
  13020 publish = false
  13021 "#,
  13022         );
  13023         write_file(
  13024             &release_policy_path,
  13025             r#"[release]
  13026 version = "1.0.0"
  13027 
  13028 [publication]
  13029 frozen = true
  13030 registry = "crates-io"
  13031 final_enablement_step = 305
  13032 
  13033 [publish]
  13034 crates = ["radroots_a"]
  13035 
  13036 [internal]
  13037 crates = ["radroots_b"]
  13038 
  13039 [publish_order]
  13040 crates = ["radroots_a"]
  13041 "#,
  13042         );
  13043         validate_release_publish_policy_with_override(
  13044             &root,
  13045             &contract_root,
  13046             "1.0.0",
  13047             Some(release_policy_path.clone()),
  13048         )
  13049         .expect("fully private workspace should satisfy publication freeze");
  13050 
  13051         write_file(
  13052             &root.join("crates").join("a").join("Cargo.toml"),
  13053             r#"[package]
  13054 name = "radroots_a"
  13055 version = "1.0.0"
  13056 edition = "2024"
  13057 publish = ["crates-io"]
  13058 "#,
  13059         );
  13060         let publishable = validate_release_publish_policy_with_override(
  13061             &root,
  13062             &contract_root,
  13063             "1.0.0",
  13064             Some(release_policy_path.clone()),
  13065         )
  13066         .expect_err("publication freeze must reject a publishable package");
  13067         assert!(publishable.contains("publication freeze requires workspace crate radroots_a"));
  13068 
  13069         write_file(
  13070             &release_policy_path,
  13071             r#"[release]
  13072 version = "1.0.0"
  13073 
  13074 [publish]
  13075 crates = ["radroots_a"]
  13076 
  13077 [internal]
  13078 crates = ["radroots_b"]
  13079 
  13080 [publish_order]
  13081 crates = ["radroots_a"]
  13082 "#,
  13083         );
  13084         let missing_control = validate_release_publish_policy_with_override(
  13085             &root,
  13086             &contract_root,
  13087             "1.0.0",
  13088             Some(release_policy_path),
  13089         )
  13090         .expect_err("release policy must carry explicit publication control");
  13091         assert!(missing_control.contains("publication control is required"));
  13092 
  13093         let _ = fs::remove_dir_all(root);
  13094     }
  13095 
  13096     #[test]
  13097     fn v1_release_policy_covers_approved_unapproved_unclassified_and_private_fixtures() {
  13098         let root = create_synthetic_workspace("v1_release_policy");
  13099         let contract_root = root.join("contracts");
  13100         let release_policy_path = root_release_policy_path(&root);
  13101         for member in ["a", "b"] {
  13102             write_file(
  13103                 &root.join("crates").join(member).join("Cargo.toml"),
  13104                 &format!(
  13105                     "[package]\nname = \"radroots_{member}\"\nversion = \"1.0.0\"\nedition = \"2024\"\npublish = false\n"
  13106                 ),
  13107             );
  13108         }
  13109 
  13110         let approved = (1..=19)
  13111             .map(|index| format!("package-{index:02}"))
  13112             .collect::<Vec<_>>();
  13113         let approved_toml = approved
  13114             .iter()
  13115             .map(|name| format!("\"{name}\""))
  13116             .collect::<Vec<_>>()
  13117             .join(", ");
  13118         let external_toml = approved[1..]
  13119             .iter()
  13120             .map(|name| format!("\"{name}\""))
  13121             .collect::<Vec<_>>()
  13122             .join(", ");
  13123         let mut architecture = format!(
  13124             "spec_id = \"radroots.crates.release.v1\"\npackage_count = 19\n\n[repositories.lib]\nversion = \"0.1.0-alpha\"\npackages = [\"package-01\"]\n\n[repositories.sdk]\nversion = \"0.1.0\"\npackages = [{external_toml}]\n"
  13125         );
  13126         for name in &approved {
  13127             architecture.push_str(&format!("\n[[package]]\nname = \"{name}\"\n"));
  13128         }
  13129         write_file(
  13130             &root.join("contracts/crates/release_v1/radroots_crates_release_v1.toml"),
  13131             &architecture,
  13132         );
  13133 
  13134         let policy = |approved_packages: &str, test_support: &str| {
  13135             format!(
  13136                 r#"[release]
  13137 version = "1.0.0"
  13138 
  13139 [publication]
  13140 frozen = true
  13141 registry = "crates-io"
  13142 final_enablement_step = 305
  13143 spec_id = "radroots.crates.release.v1"
  13144 approved_packages = [{approved_packages}]
  13145 local_packages = ["package-01"]
  13146 external_packages = [{external_toml}]
  13147 
  13148 [workspace_classification]
  13149 private = ["radroots_a"]
  13150 build_codegen = []
  13151 test_support = [{test_support}]
  13152 preview = []
  13153 retired = []
  13154 
  13155 [publish_order]
  13156 crates = []
  13157 "#
  13158             )
  13159         };
  13160 
  13161         write_file(
  13162             &release_policy_path,
  13163             &policy(&approved_toml, "\"radroots_b\""),
  13164         );
  13165         validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13166             .expect("approved and exhaustively classified fixture must pass");
  13167 
  13168         let unapproved = format!("{approved_toml}, \"unapproved-public\"");
  13169         write_file(&release_policy_path, &policy(&unapproved, "\"radroots_b\""));
  13170         let unapproved_error = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13171             .expect_err("unapproved public package must fail");
  13172         assert!(unapproved_error.contains("unapproved packages: unapproved-public"));
  13173 
  13174         write_file(&release_policy_path, &policy(&approved_toml, ""));
  13175         let unclassified = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13176             .expect_err("unclassified workspace package must fail");
  13177         assert!(unclassified.contains("workspace classification is missing packages: radroots_b"));
  13178 
  13179         write_file(
  13180             &release_policy_path,
  13181             &policy(&approved_toml, "\"radroots_b\""),
  13182         );
  13183         write_file(
  13184             &root.join("crates/a/Cargo.toml"),
  13185             "[package]\nname = \"radroots_a\"\nversion = \"1.0.0\"\nedition = \"2024\"\npublish = [\"crates-io\"]\n",
  13186         );
  13187         let private = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13188             .expect_err("private package must remain non-publishable");
  13189         assert!(private.contains("publication freeze requires workspace crate radroots_a"));
  13190 
  13191         let _ = fs::remove_dir_all(root);
  13192     }
  13193 
  13194     #[test]
  13195     fn release_preflight_rejects_public_dto_tooling_git_or_path_sources() {
  13196         let root = create_synthetic_workspace("release_policy_dto_tooling_sources");
  13197 
  13198         write_file(
  13199             &root.join("crates").join("a").join("Cargo.toml"),
  13200             r#"[package]
  13201 name = "radroots_a"
  13202 publish = ["crates-io"]
  13203 version = "1.0.0"
  13204 edition = "2024"
  13205 authors = ["Radroots Test"]
  13206 rust-version = "1.97"
  13207 license = "MIT OR Apache-2.0"
  13208 description = "crate a"
  13209 repository = "https://example.com/a"
  13210 homepage = "https://example.com/a"
  13211 documentation = "https://docs.rs/radroots_a"
  13212 readme = "README.md"
  13213 keywords = ["radroots"]
  13214 categories = ["data-structures"]
  13215 include = ["src/**", "tests/**", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
  13216 
  13217 [package.metadata.docs.rs]
  13218 features = []
  13219 
  13220 [dependencies]
  13221 dto_bindgen_core = { path = "../../dto_bindgen_core", version = "0.1.0", optional = true }
  13222 "#,
  13223         );
  13224         let path_err =
  13225             validate_generic_release_preflight(&root).expect_err("public path DTO dependency");
  13226         assert!(path_err.contains("radroots_a dependencies.dto_bindgen_core"));
  13227         assert!(path_err.contains("not a path source"));
  13228 
  13229         write_file(
  13230             &root.join("Cargo.toml"),
  13231             r#"[workspace]
  13232 members = ["crates/a", "crates/b"]
  13233 resolver = "2"
  13234 
  13235 [workspace.package]
  13236 version = "1.0.0"
  13237 
  13238 [workspace.dependencies]
  13239 dto_bindgen = { version = "0.1.0", git = "https://example.com/dto_bindgen", rev = "abc123" }
  13240 radroots_a = { path = "crates/a", version = "=1.0.0" }
  13241 radroots_b = { path = "crates/b", version = "=1.0.0" }
  13242 "#,
  13243         );
  13244         write_file(
  13245             &root.join("crates").join("a").join("Cargo.toml"),
  13246             r#"[package]
  13247 name = "radroots_a"
  13248 publish = ["crates-io"]
  13249 version = "1.0.0"
  13250 edition = "2024"
  13251 description = "crate a"
  13252 repository = "https://example.com/a"
  13253 homepage = "https://example.com/a"
  13254 documentation = "https://docs.example.com/a"
  13255 readme = "README"
  13256 
  13257 [dependencies]
  13258 dto_bindgen = { workspace = true, optional = true }
  13259 "#,
  13260         );
  13261         let git_err = validate_generic_release_preflight(&root)
  13262             .expect_err("public workspace git DTO dependency");
  13263         assert!(git_err.contains("radroots_a dependencies.dto_bindgen"));
  13264         assert!(git_err.contains("not a git source"));
  13265 
  13266         write_file(
  13267             &root.join("crates").join("a").join("Cargo.toml"),
  13268             r#"[package]
  13269 name = "radroots_a"
  13270 publish = ["crates-io"]
  13271 version = "1.0.0"
  13272 edition = "2024"
  13273 authors = ["Radroots Test"]
  13274 rust-version = "1.97"
  13275 license = "MIT OR Apache-2.0"
  13276 description = "crate a"
  13277 repository = "https://example.com/a"
  13278 homepage = "https://example.com/a"
  13279 documentation = "https://docs.rs/radroots_a"
  13280 readme = "README.md"
  13281 keywords = ["radroots"]
  13282 categories = ["data-structures"]
  13283 include = ["src/**", "tests/**", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
  13284 
  13285 [package.metadata.docs.rs]
  13286 features = []
  13287 "#,
  13288         );
  13289         write_file(
  13290             &root.join("crates").join("b").join("Cargo.toml"),
  13291             r#"[package]
  13292 name = "radroots_b"
  13293 version = "1.0.0"
  13294 edition = "2024"
  13295 publish = false
  13296 
  13297 [dependencies]
  13298 dto_bindgen = { workspace = true, optional = true }
  13299 
  13300 [features]
  13301 default = ["std"]
  13302 std = []
  13303 legacy-ingest = ["std"]
  13304 "#,
  13305         );
  13306         validate_generic_release_preflight(&root)
  13307             .expect("internal DTO tooling source does not block public publish policy");
  13308 
  13309         let _ = fs::remove_dir_all(root);
  13310     }
  13311 
  13312     #[test]
  13313     fn validate_contract_bundle_reports_required_field_errors() {
  13314         let root = create_synthetic_workspace("contract_bundle_errors");
  13315 
  13316         let assert_bundle_error = |expected: &str, mutator: fn(&mut ContractBundle)| {
  13317             let mut bundle = load_contract_bundle(&root).expect("load bundle");
  13318             mutator(&mut bundle);
  13319             let err = match validate_generic_contract_bundle(&bundle) {
  13320                 Ok(()) => panic!("expected bundle validation error: {expected}"),
  13321                 Err(err) => err,
  13322             };
  13323             assert!(err.contains(expected), "expected `{expected}` in `{err}`");
  13324         };
  13325 
  13326         assert_bundle_error("contract name is required", |bundle| {
  13327             bundle.manifest.contract.name.clear();
  13328         });
  13329         assert_bundle_error("contract version is required", |bundle| {
  13330             bundle.manifest.contract.version.clear();
  13331         });
  13332         assert_bundle_error("contract source is required", |bundle| {
  13333             bundle.manifest.contract.source.clear();
  13334         });
  13335         assert_bundle_error("surface.model_crates must not be empty", |bundle| {
  13336             bundle.manifest.surface.model_crates.clear();
  13337         });
  13338         assert_bundle_error("surface.algorithm_crates must not be empty", |bundle| {
  13339             bundle.manifest.surface.algorithm_crates.clear();
  13340         });
  13341         assert_bundle_error(
  13342             "surface.internal_replica_crates.storage must be a crate identifier",
  13343             |bundle| {
  13344                 bundle.manifest.surface.internal_replica_crates = Some(InternalReplicaCrates {
  13345                     schema: "radroots_replica_schema".to_string(),
  13346                     storage: "crates/replica_store".to_string(),
  13347                     sync: "radroots_replica_sync".to_string(),
  13348                 });
  13349             },
  13350         );
  13351         assert_bundle_error("version.contract.version is required", |bundle| {
  13352             bundle.version.contract.version.clear();
  13353         });
  13354         assert_bundle_error("version.contract.stability is required", |bundle| {
  13355             bundle.version.contract.stability.clear();
  13356         });
  13357         assert_bundle_error("version.semver rules must all be non-empty", |bundle| {
  13358             bundle.version.semver.major_on.clear();
  13359         });
  13360         assert_bundle_error("version.semver rules must all be non-empty", |bundle| {
  13361             bundle.version.semver.minor_on.clear();
  13362         });
  13363         assert_bundle_error("version.semver rules must all be non-empty", |bundle| {
  13364             bundle.version.semver.patch_on.clear();
  13365         });
  13366         assert_bundle_error(
  13367             "release_integrity.requires_conformance_pass must be true",
  13368             |bundle| {
  13369                 bundle.version.release_integrity.requires_conformance_pass = false;
  13370             },
  13371         );
  13372         assert_bundle_error(
  13373             "release_integrity.requires_contract_manifest_diff must be true",
  13374             |bundle| {
  13375                 bundle
  13376                     .version
  13377                     .release_integrity
  13378                     .requires_contract_manifest_diff = false;
  13379             },
  13380         );
  13381         assert_bundle_error(
  13382             "release_integrity.requires_release_notes must be true",
  13383             |bundle| {
  13384                 bundle.version.release_integrity.requires_release_notes = false;
  13385             },
  13386         );
  13387         assert_bundle_error("contract policy flags must all be true", |bundle| {
  13388             bundle.manifest.policy.exclude_internal_workspace_crates = false;
  13389         });
  13390         assert_bundle_error("contract policy flags must all be true", |bundle| {
  13391             bundle.manifest.policy.require_reproducible_exports = false;
  13392         });
  13393         assert_bundle_error("contract policy flags must all be true", |bundle| {
  13394             bundle.manifest.policy.require_conformance_vectors = false;
  13395         });
  13396         assert_bundle_error("contract replica policy flags must all be true", |bundle| {
  13397             bundle.manifest.policy.replica = Some(ReplicaPolicy {
  13398                 forbid_legacy_alias_identifiers: false,
  13399                 require_transport_agnostic_sync_contract: true,
  13400                 require_deterministic_emit_ingest: true,
  13401             });
  13402         });
  13403 
  13404         let _ = fs::remove_dir_all(root);
  13405     }
  13406 
  13407     #[test]
  13408     fn load_contract_bundle_rejects_stale_consumer_sdk_tables() {
  13409         let stale_manifest_root = create_synthetic_workspace("stale_manifest_consumer_sdk");
  13410         let manifest_path = stale_manifest_root.join("contracts").join("manifest.toml");
  13411         let mut manifest = fs::read_to_string(&manifest_path).expect("manifest");
  13412         manifest.push_str(
  13413             r#"
  13414 [consumer_sdk]
  13415 rust_package = "radroots_sdk"
  13416 "#,
  13417         );
  13418         write_file(&manifest_path, &manifest);
  13419         let manifest_err =
  13420             load_contract_bundle(&stale_manifest_root).expect_err("stale manifest table");
  13421         assert!(manifest_err.contains("manifest.toml"));
  13422         assert!(manifest_err.contains("consumer_sdk"));
  13423         let _ = fs::remove_dir_all(stale_manifest_root);
  13424 
  13425         let stale_operations_root = create_synthetic_workspace("stale_operations_consumer_sdk");
  13426         add_operation_contract_files(&stale_operations_root);
  13427         let operations_path = stale_operations_root
  13428             .join("contracts")
  13429             .join("operations.toml");
  13430         let mut operations = fs::read_to_string(&operations_path).expect("operations");
  13431         operations.push_str(
  13432             r#"
  13433 [consumer_sdk]
  13434 rust_package = "radroots_sdk"
  13435 "#,
  13436         );
  13437         write_file(&operations_path, &operations);
  13438         let operations_err =
  13439             load_contract_bundle(&stale_operations_root).expect_err("stale operations table");
  13440         assert!(operations_err.contains("operations.toml"));
  13441         assert!(operations_err.contains("consumer_sdk"));
  13442         let _ = fs::remove_dir_all(stale_operations_root);
  13443     }
  13444 
  13445     #[test]
  13446     fn load_contract_bundle_rejects_legacy_contract_roots() {
  13447         let stale_spec_root = create_synthetic_workspace("stale_spec_root");
  13448         fs::create_dir_all(stale_spec_root.join("spec")).expect("create spec root");
  13449         let spec_err = load_contract_bundle(&stale_spec_root).expect_err("stale spec root");
  13450         assert!(spec_err.contains("legacy contract root"));
  13451         assert!(spec_err.contains("spec"));
  13452         let _ = fs::remove_dir_all(stale_spec_root);
  13453 
  13454         let stale_policy_root = create_synthetic_workspace("stale_policy_root");
  13455         fs::create_dir_all(stale_policy_root.join("policy")).expect("create policy root");
  13456         let policy_err = load_contract_bundle(&stale_policy_root).expect_err("stale policy root");
  13457         assert!(policy_err.contains("legacy contract root"));
  13458         assert!(policy_err.contains("policy"));
  13459         let _ = fs::remove_dir_all(stale_policy_root);
  13460     }
  13461 
  13462     #[test]
  13463     fn load_contract_bundle_requires_operations_manifest() {
  13464         let root = create_synthetic_workspace("missing_operations_manifest");
  13465         fs::remove_file(root.join("contracts").join("operations.toml"))
  13466             .expect("remove operations manifest");
  13467 
  13468         let error = load_contract_bundle(&root).expect_err("missing operations manifest");
  13469         assert!(error.contains("operations.toml"), "{error}");
  13470         assert!(error.contains("read"), "{error}");
  13471 
  13472         let _ = fs::remove_dir_all(root);
  13473     }
  13474 
  13475     #[test]
  13476     fn capsule_operation_authority_cannot_be_disabled_by_domain_removal() {
  13477         let root = workspace_root();
  13478 
  13479         let mut social_bundle = load_contract_bundle(&root).expect("load current contract");
  13480         social_bundle
  13481             .operations_manifest
  13482             .public
  13483             .domains
  13484             .retain(|domain| domain != "social");
  13485         social_bundle
  13486             .operations_manifest
  13487             .operations
  13488             .retain(|_, operation| operation.domain != "social");
  13489         let social_error = validate_contract_bundle(&social_bundle)
  13490             .expect_err("removing social authority must fail");
  13491         assert!(
  13492             social_error.contains("comment operation authority drift"),
  13493             "{social_error}"
  13494         );
  13495 
  13496         let mut food_bundle = load_contract_bundle(&root).expect("load current contract");
  13497         food_bundle
  13498             .operations_manifest
  13499             .public
  13500             .domains
  13501             .retain(|domain| domain != "food_availability");
  13502         food_bundle
  13503             .operations_manifest
  13504             .operations
  13505             .retain(|_, operation| operation.domain != "food_availability");
  13506         let food_error = validate_contract_bundle(&food_bundle)
  13507             .expect_err("removing FoodAvailability authority must fail");
  13508         assert!(
  13509             food_error.contains("food availability operation authority drift"),
  13510             "{food_error}"
  13511         );
  13512     }
  13513 
  13514     #[test]
  13515     fn validate_contract_bundle_reports_operation_contract_errors() {
  13516         let root = create_synthetic_workspace("operation_contract_bundle_errors");
  13517         add_operation_contract_files(&root);
  13518 
  13519         let assert_bundle_error = |expected: &str, mutator: fn(&mut ContractBundle)| {
  13520             let mut bundle = load_contract_bundle(&root).expect("load bundle");
  13521             mutator(&mut bundle);
  13522             let err =
  13523                 validate_generic_contract_bundle(&bundle).expect_err("bundle validation error");
  13524             assert!(err.contains(expected), "expected `{expected}` in `{err}`");
  13525         };
  13526 
  13527         assert_bundle_error("public.domains must not be empty", |bundle| {
  13528             bundle.operations_manifest.public.domains.clear();
  13529         });
  13530         assert_bundle_error(
  13531             "shared_types.public uses retired event type RadrootsNostrEvent",
  13532             |bundle| {
  13533                 bundle
  13534                     .operations_manifest
  13535                     .shared_types
  13536                     .public
  13537                     .push("RadrootsNostrEvent".to_string());
  13538             },
  13539         );
  13540         assert_bundle_error(
  13541             "shared_types.public uses retired event type RadrootsInboundCalendarDateEvent",
  13542             |bundle| {
  13543                 bundle
  13544                     .operations_manifest
  13545                     .shared_types
  13546                     .public
  13547                     .push("RadrootsInboundCalendarDateEvent".to_string());
  13548             },
  13549         );
  13550         assert_bundle_error(
  13551             "shared_types.public uses retired event type RadrootsCalendar",
  13552             |bundle| {
  13553                 bundle
  13554                     .operations_manifest
  13555                     .shared_types
  13556                     .public
  13557                     .push("RadrootsCalendar".to_string());
  13558             },
  13559         );
  13560         assert_bundle_error(
  13561             "shared_types.public uses retired event type RadrootsCalendarEventRsvp",
  13562             |bundle| {
  13563                 bundle
  13564                     .operations_manifest
  13565                     .shared_types
  13566                     .public
  13567                     .push("RadrootsCalendarEventRsvp".to_string());
  13568             },
  13569         );
  13570         assert_bundle_error(
  13571             "shared_types.public uses retired event type RadrootsCalendarRsvp",
  13572             |bundle| {
  13573                 bundle
  13574                     .operations_manifest
  13575                     .shared_types
  13576                     .public
  13577                     .push("RadrootsCalendarRsvp".to_string());
  13578             },
  13579         );
  13580         assert_bundle_error(
  13581             "operation profile.build_authored_draft inputs uses retired event type RadrootsNostrEvent",
  13582             |bundle| {
  13583                 bundle
  13584                     .operations_manifest
  13585                     .operations
  13586                     .get_mut("profile_build_authored_draft")
  13587                     .expect("profile operation")
  13588                     .inputs
  13589                     .push("RadrootsNostrEvent".to_string());
  13590             },
  13591         );
  13592         assert_bundle_error(
  13593             "operation profile.build_authored_draft outputs uses retired event type WireEventParts",
  13594             |bundle| {
  13595                 bundle
  13596                     .operations_manifest
  13597                     .operations
  13598                     .get_mut("profile_build_authored_draft")
  13599                     .expect("profile operation")
  13600                     .outputs
  13601                     .push("WireEventParts".to_string());
  13602             },
  13603         );
  13604         assert_bundle_error(
  13605             "operation profile.build_authored_draft implementation.rust_types uses retired event type RadrootsNostrEventPtr",
  13606             |bundle| {
  13607                 bundle
  13608                     .operations_manifest
  13609                     .operations
  13610                     .get_mut("profile_build_authored_draft")
  13611                     .expect("profile operation")
  13612                     .implementation
  13613                     .rust_types
  13614                     .push("radroots_event::RadrootsNostrEventPtr".to_string());
  13615             },
  13616         );
  13617         let _ = fs::remove_dir_all(root);
  13618     }
  13619 
  13620     #[test]
  13621     fn validate_contract_bundle_requires_real_conformance_assets() {
  13622         let missing_schema_root = create_synthetic_workspace("operation_contract_missing_schema");
  13623         add_operation_contract_files(&missing_schema_root);
  13624         let _ = fs::remove_file(conformance_schema_path(&missing_schema_root));
  13625         let bundle = load_contract_bundle(&missing_schema_root).expect("load bundle");
  13626         let err =
  13627             validate_generic_contract_bundle(&bundle).expect_err("missing schema should fail");
  13628         assert!(err.contains("vector.schema.json"));
  13629         let _ = fs::remove_dir_all(&missing_schema_root);
  13630 
  13631         let invalid_vector_root = create_synthetic_workspace("operation_contract_invalid_vector");
  13632         add_operation_contract_files(&invalid_vector_root);
  13633         let invalid_vector_path = invalid_vector_root
  13634             .join("contracts")
  13635             .join("conformance")
  13636             .join("vectors")
  13637             .join("profile")
  13638             .join("metadata.v1.json");
  13639         write_file(
  13640             &invalid_vector_path,
  13641             r#"{
  13642   "suite": "profile",
  13643   "contract_version": "1.0.0",
  13644   "vectors": [
  13645     {
  13646       "id": "profile_build_authored_draft_minimal_001",
  13647       "kind": "profile.build_authored_draft",
  13648       "input": {}
  13649     }
  13650   ]
  13651 }
  13652 "#,
  13653         );
  13654         let bundle = load_contract_bundle(&invalid_vector_root).expect("load bundle");
  13655         let err =
  13656             validate_generic_contract_bundle(&bundle).expect_err("invalid vector should fail");
  13657         assert!(err.contains("metadata.v1.json"));
  13658         assert!(err.contains("exactly one of expected or expected_error_contains"));
  13659 
  13660         write_file(
  13661             &invalid_vector_path,
  13662             r#"{
  13663   "suite": "profile",
  13664   "contract_version": "1.0.0",
  13665   "vectors": [
  13666     {
  13667       "id": "profile_build_authored_draft_minimal_001",
  13668       "kind": "profile.build_authored_draft",
  13669       "input": {},
  13670       "expected": {},
  13671       "expected_error_contains": "invalid"
  13672     }
  13673   ]
  13674 }
  13675 "#,
  13676         );
  13677         let err = validate_generic_contract_bundle(&bundle)
  13678             .expect_err("vector with two result authorities should fail");
  13679         assert!(err.contains("exactly one of expected or expected_error_contains"));
  13680 
  13681         write_file(
  13682             &invalid_vector_path,
  13683             r#"{
  13684   "suite": "profile",
  13685   "contract_version": "1.0.0",
  13686   "vectors": [
  13687     {
  13688       "id": "profile_build_authored_draft_minimal_001",
  13689       "kind": "profile.build_authored_draft",
  13690       "input": {},
  13691       "expected_error_contains": "   "
  13692     }
  13693   ]
  13694 }
  13695 "#,
  13696         );
  13697         let err = validate_generic_contract_bundle(&bundle)
  13698             .expect_err("blank expected error fragment should fail");
  13699         assert!(err.contains("expected_error_contains must not be blank"));
  13700         let _ = fs::remove_dir_all(&invalid_vector_root);
  13701 
  13702         let root = create_synthetic_workspace("operation_contract_vector_path");
  13703         add_operation_contract_files(&root);
  13704         let mut bundle = load_contract_bundle(&root).expect("load bundle");
  13705         bundle
  13706             .operations_manifest
  13707             .operations
  13708             .get_mut("profile_build_authored_draft")
  13709             .expect("profile operation")
  13710             .conformance
  13711             .vector = "conformance/vectors/profile/metadata.v1.json".to_string();
  13712         let err = validate_generic_contract_bundle(&bundle).expect_err("legacy path should fail");
  13713         assert!(err.contains("must live under contracts/conformance/"));
  13714         let _ = fs::remove_dir_all(root);
  13715     }
  13716 
  13717     #[test]
  13718     fn parse_toml_and_publish_flags_report_failures() {
  13719         let missing = temp_root("parse_toml_missing");
  13720         let read_err =
  13721             parse_toml::<WorkspaceCargoManifest>(&missing.join("Cargo.toml")).expect_err("missing");
  13722         assert!(read_err.contains("read"));
  13723         let _ = fs::remove_dir_all(&missing);
  13724 
  13725         let invalid = temp_root("parse_toml_invalid");
  13726         write_file(&invalid.join("Cargo.toml"), "[workspace]\nmembers = [");
  13727         let parse_err = parse_toml::<WorkspaceCargoManifest>(&invalid.join("Cargo.toml"))
  13728             .expect_err("invalid manifest");
  13729         assert!(parse_err.contains("parse"));
  13730         let _ = fs::remove_dir_all(&invalid);
  13731 
  13732         let contract_manifest_missing = temp_root("parse_contract_manifest_missing");
  13733         let contract_manifest_read_err =
  13734             parse_toml::<ContractManifest>(&contract_manifest_missing.join("manifest.toml"))
  13735                 .expect_err("missing contract manifest");
  13736         assert!(contract_manifest_read_err.contains("read"));
  13737         let _ = fs::remove_dir_all(&contract_manifest_missing);
  13738 
  13739         let contract_manifest_invalid = temp_root("parse_contract_manifest_invalid");
  13740         write_file(
  13741             &contract_manifest_invalid.join("manifest.toml"),
  13742             "[contract",
  13743         );
  13744         let contract_manifest_parse_err =
  13745             parse_toml::<ContractManifest>(&contract_manifest_invalid.join("manifest.toml"))
  13746                 .expect_err("invalid contract manifest");
  13747         assert!(contract_manifest_parse_err.contains("parse"));
  13748         let _ = fs::remove_dir_all(&contract_manifest_invalid);
  13749 
  13750         let version_missing = temp_root("parse_version_policy_missing");
  13751         let version_read_err = parse_toml::<VersionPolicy>(&version_missing.join("version.toml"))
  13752             .expect_err("missing version policy");
  13753         assert!(version_read_err.contains("read"));
  13754         let _ = fs::remove_dir_all(&version_missing);
  13755 
  13756         let version_invalid = temp_root("parse_version_policy_invalid");
  13757         write_file(&version_invalid.join("version.toml"), "[version");
  13758         let version_parse_err = parse_toml::<VersionPolicy>(&version_invalid.join("version.toml"))
  13759             .expect_err("invalid version policy");
  13760         assert!(version_parse_err.contains("parse"));
  13761         let _ = fs::remove_dir_all(&version_invalid);
  13762 
  13763         let release_missing = temp_root("parse_release_contract_missing");
  13764         let release_read_err =
  13765             parse_toml::<ReleaseContractFile>(&release_missing.join("publish-set.toml"))
  13766                 .expect_err("missing release contract");
  13767         assert!(release_read_err.contains("read"));
  13768         let _ = fs::remove_dir_all(&release_missing);
  13769 
  13770         let release_invalid = temp_root("parse_release_contract_invalid");
  13771         write_file(&release_invalid.join("publish-set.toml"), "[release");
  13772         let release_parse_err =
  13773             parse_toml::<ReleaseContractFile>(&release_invalid.join("publish-set.toml"))
  13774                 .expect_err("invalid release contract");
  13775         assert!(release_parse_err.contains("parse"));
  13776         let _ = fs::remove_dir_all(&release_invalid);
  13777 
  13778         let operations_missing = temp_root("parse_operations_manifest_missing");
  13779         let operations_read_err =
  13780             parse_toml::<OperationsContractManifest>(&operations_missing.join("operations.toml"))
  13781                 .expect_err("missing operations manifest");
  13782         assert!(operations_read_err.contains("read"));
  13783         let _ = fs::remove_dir_all(&operations_missing);
  13784 
  13785         let operations_invalid = temp_root("parse_operations_manifest_invalid");
  13786         write_file(&operations_invalid.join("operations.toml"), "[operations");
  13787         let operations_parse_err =
  13788             parse_toml::<OperationsContractManifest>(&operations_invalid.join("operations.toml"))
  13789                 .expect_err("invalid operations manifest");
  13790         assert!(operations_parse_err.contains("parse"));
  13791         let _ = fs::remove_dir_all(&operations_invalid);
  13792 
  13793         let dup = temp_root("publish_flags_duplicate");
  13794         write_file(
  13795             &dup.join("Cargo.toml"),
  13796             r#"[workspace]
  13797 members = ["crates/a", "crates/b"]
  13798 "#,
  13799         );
  13800         let member_manifest =
  13801             "[package]\nname = \"duplicate\"\nversion = \"0.1.0\"\nedition = \"2024\"\n";
  13802         write_file(
  13803             &dup.join("crates").join("a").join("Cargo.toml"),
  13804             member_manifest,
  13805         );
  13806         write_file(
  13807             &dup.join("crates").join("b").join("Cargo.toml"),
  13808             member_manifest,
  13809         );
  13810         let dup_err = workspace_package_publish_flags(&dup).expect_err("duplicate publish flags");
  13811         assert!(dup_err.contains("duplicate workspace package name"));
  13812         let _ = fs::remove_dir_all(&dup);
  13813     }
  13814 
  13815     #[test]
  13816     fn workspace_package_records_and_callers_report_member_manifest_errors() {
  13817         let root = temp_root("workspace_package_record_errors");
  13818         write_file(
  13819             &root.join("Cargo.toml"),
  13820             r#"[workspace]
  13821 members = ["crates/a"]
  13822 "#,
  13823         );
  13824 
  13825         let read_err =
  13826             workspace_package_records(&root).expect_err("missing member manifest should fail");
  13827         assert!(read_err.contains("read"));
  13828 
  13829         let names_err = workspace_package_names(&root).expect_err("names should fail");
  13830         assert!(names_err.contains("read"));
  13831         let manifests_err = workspace_package_manifests(&root).expect_err("manifests should fail");
  13832         assert!(manifests_err.contains("read"));
  13833         let flags_err = workspace_package_publish_flags(&root).expect_err("flags should fail");
  13834         assert!(flags_err.contains("read"));
  13835         let deps_err = read_workspace_package_dependencies(&root).expect_err("deps should fail");
  13836         assert!(deps_err.contains("read"));
  13837 
  13838         let publish = ["radroots_a".to_string()]
  13839             .into_iter()
  13840             .collect::<BTreeSet<_>>();
  13841         let publish_err =
  13842             validate_publish_package_metadata(&root, &publish).expect_err("publish metadata");
  13843         assert!(publish_err.contains("read"));
  13844 
  13845         write_file(
  13846             &root.join("crates").join("a").join("Cargo.toml"),
  13847             "[package",
  13848         );
  13849         let parse_value_err =
  13850             workspace_package_records(&root).expect_err("invalid toml should fail");
  13851         assert!(parse_value_err.contains("parse"));
  13852 
  13853         write_file(
  13854             &root.join("crates").join("a").join("Cargo.toml"),
  13855             r#"[workspace]
  13856 resolver = "2"
  13857 "#,
  13858         );
  13859         let parse_package_err =
  13860             workspace_package_records(&root).expect_err("missing package table should fail");
  13861         assert!(parse_package_err.contains("parse"));
  13862 
  13863         let _ = fs::remove_dir_all(&root);
  13864     }
  13865 
  13866     #[test]
  13867     fn workspace_package_manifests_success_and_publish_metadata_duplicate_names() {
  13868         let root = create_synthetic_workspace("workspace_manifest_success");
  13869         let manifests = workspace_package_manifests(&root).expect("workspace manifests");
  13870         assert_eq!(manifests.len(), 2);
  13871         assert!(manifests.contains_key("radroots_a"));
  13872         assert!(manifests.contains_key("radroots_b"));
  13873 
  13874         write_file(
  13875             &root.join("crates").join("b").join("Cargo.toml"),
  13876             r#"[package]
  13877 name = "radroots_a"
  13878 version = "1.0.0"
  13879 edition = "2024"
  13880 description = "crate b duplicate name"
  13881 repository = "https://example.com/b"
  13882 homepage = "https://example.com/b"
  13883 documentation = "https://docs.example.com/b"
  13884 readme = "README"
  13885 publish = false
  13886 "#,
  13887         );
  13888         let publish = ["radroots_a".to_string()]
  13889             .into_iter()
  13890             .collect::<BTreeSet<_>>();
  13891         let duplicate_err =
  13892             validate_publish_package_metadata(&root, &publish).expect_err("duplicate package map");
  13893         assert!(duplicate_err.contains("duplicate workspace package name"));
  13894 
  13895         let _ = fs::remove_dir_all(&root);
  13896     }
  13897 
  13898     #[test]
  13899     fn workspace_package_publish_configs_cover_success_and_duplicate_names() {
  13900         let root = create_synthetic_workspace("workspace_publish_configs");
  13901         let flags = workspace_package_publish_flags(&root).expect("publish flags");
  13902         assert!(flags["radroots_a"]);
  13903         assert!(!flags["radroots_b"]);
  13904 
  13905         let configs = workspace_package_publish_configs(&root).expect("publish configs");
  13906         assert_eq!(
  13907             configs["radroots_a"],
  13908             Some(PackagePublish::Registries(vec!["crates-io".to_string()]))
  13909         );
  13910         assert_eq!(configs["radroots_b"], Some(PackagePublish::Bool(false)));
  13911 
  13912         write_file(
  13913             &root.join("crates").join("b").join("Cargo.toml"),
  13914             r#"[package]
  13915 name = "radroots_a"
  13916 version = "1.0.0"
  13917 edition = "2024"
  13918 publish = false
  13919 "#,
  13920         );
  13921         let duplicate_err = workspace_package_publish_configs(&root)
  13922             .expect_err("duplicate package name in publish configs");
  13923         assert!(duplicate_err.contains("duplicate workspace package name"));
  13924 
  13925         let _ = fs::remove_dir_all(&root);
  13926     }
  13927 
  13928     #[test]
  13929     fn workspace_package_publish_configs_report_workspace_record_errors() {
  13930         let root = temp_root("workspace_publish_configs_errors");
  13931         let err = workspace_package_publish_configs(&root)
  13932             .expect_err("missing workspace manifest should fail");
  13933         assert!(err.contains("Cargo.toml"));
  13934 
  13935         let _ = fs::remove_dir_all(&root);
  13936     }
  13937 
  13938     #[test]
  13939     fn coverage_release_and_bundle_loaders_report_parse_and_read_errors() {
  13940         let root = create_synthetic_workspace("coverage_release_loader_errors");
  13941         let contract_root = root.join("contracts");
  13942         let coverage_root = coverage_root(&contract_root);
  13943         let release_policy_path = root_release_policy_path(&root);
  13944 
  13945         let missing_workspace = temp_root("coverage_missing_workspace_manifest");
  13946         let policy_workspace_err =
  13947             validate_coverage_policy_parity(&missing_workspace, &contract_root)
  13948                 .expect_err("coverage workspace lookup error");
  13949         assert!(policy_workspace_err.contains("Cargo.toml"));
  13950         let _ = fs::remove_dir_all(&missing_workspace);
  13951 
  13952         let _ = fs::remove_file(coverage_root.join("coverage.toml"));
  13953         let policy_load_err = validate_coverage_policy_parity(&root, &contract_root)
  13954             .expect_err("coverage policy read error");
  13955         assert!(policy_load_err.contains("coverage.toml"));
  13956         write_file(
  13957             &coverage_root.join("coverage.toml"),
  13958             r#"[gate]
  13959 fail_under_exec_lines = 100.0
  13960 fail_under_functions = 100.0
  13961 fail_under_regions = 100.0
  13962 fail_under_branches = 100.0
  13963 require_branches = true
  13964 
  13965 [required]
  13966 crates = ["radroots_a", "radroots_b"]
  13967 "#,
  13968         );
  13969 
  13970         let missing_release = temp_root("release_missing_workspace_manifest");
  13971         write_root_release_policy(
  13972             &missing_release,
  13973             r#"[release]
  13974 version = "1.0.0"
  13975 
  13976 [publish]
  13977 crates = ["radroots_a"]
  13978 
  13979 [internal]
  13980 crates = ["radroots_b"]
  13981 
  13982 [publish_order]
  13983 crates = ["radroots_a"]
  13984 "#,
  13985         );
  13986         let release_workspace_err =
  13987             validate_release_publish_policy(&missing_release, &contract_root, "1.0.0")
  13988                 .expect_err("release workspace read error");
  13989         assert!(release_workspace_err.contains("Cargo.toml"));
  13990         let _ = fs::remove_dir_all(&missing_release);
  13991 
  13992         let _ = fs::remove_file(&release_policy_path);
  13993         let release_load_err = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  13994             .expect_err("release contract read error");
  13995         assert!(release_load_err.contains(RELEASE_POLICY_RELATIVE));
  13996 
  13997         write_file(
  13998             &release_policy_path,
  13999             r#"[release]
  14000 version = "1.0.0"
  14001 
  14002 [publish]
  14003 crates = ["radroots_a", "radroots_a"]
  14004 
  14005 [internal]
  14006 crates = ["radroots_b"]
  14007 
  14008 [publish_order]
  14009 crates = ["radroots_a"]
  14010 "#,
  14011         );
  14012         let duplicate_publish = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14013             .expect_err("duplicate publish crates");
  14014         assert!(duplicate_publish.contains("publish.crates has duplicate crate"));
  14015 
  14016         write_file(
  14017             &release_policy_path,
  14018             r#"[release]
  14019 version = "1.0.0"
  14020 
  14021 [publish]
  14022 crates = ["radroots_a"]
  14023 
  14024 [internal]
  14025 crates = ["radroots_b", "radroots_b"]
  14026 
  14027 [publish_order]
  14028 crates = ["radroots_a"]
  14029 "#,
  14030         );
  14031         let duplicate_internal = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14032             .expect_err("duplicate internal crates");
  14033         assert!(duplicate_internal.contains("internal.crates has duplicate crate"));
  14034 
  14035         write_file(
  14036             &release_policy_path,
  14037             r#"[release]
  14038 version = "1.0.0"
  14039 
  14040 [publish]
  14041 crates = ["radroots_a"]
  14042 
  14043 [internal]
  14044 crates = ["radroots_b"]
  14045 
  14046 [publish_order]
  14047 crates = ["radroots_a", "radroots_a"]
  14048 "#,
  14049         );
  14050         let duplicate_order = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14051             .expect_err("duplicate publish order");
  14052         assert!(duplicate_order.contains("publish_order.crates has duplicate crate"));
  14053 
  14054         write_file(
  14055             &release_policy_path,
  14056             r#"[release]
  14057 version = "1.0.0"
  14058 
  14059 [publish]
  14060 crates = ["radroots_a"]
  14061 
  14062 [internal]
  14063 crates = ["radroots_b"]
  14064 
  14065 [publish_order]
  14066 crates = ["radroots_a"]
  14067 "#,
  14068         );
  14069         write_file(
  14070             &root.join("crates").join("a").join("Cargo.toml"),
  14071             "[package",
  14072         );
  14073         let dependency_err = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14074             .expect_err("workspace dependency parse error");
  14075         assert!(dependency_err.contains("parse"));
  14076 
  14077         let _ = fs::remove_dir_all(&root);
  14078     }
  14079 
  14080     #[test]
  14081     fn load_release_contract_with_override_reports_override_and_missing_policy_errors() {
  14082         let root = create_synthetic_workspace("release_contract_loader_errors");
  14083 
  14084         let missing_override = root.join("missing-release-policy.toml");
  14085         let override_err =
  14086             load_release_contract_with_override(&root, "1.0.0", Some(missing_override.clone()))
  14087                 .expect_err("missing override should fail");
  14088         assert!(override_err.contains("release policy override points to a missing file"));
  14089 
  14090         let _ = fs::remove_file(root_release_policy_path(&root));
  14091         let missing_policy_err = load_release_contract_with_override(&root, "1.0.0", None)
  14092             .expect_err("missing release policy should fail");
  14093         assert!(missing_policy_err.contains("release publish policy not found"));
  14094         assert!(missing_policy_err.contains(RELEASE_POLICY_RELATIVE));
  14095 
  14096         let _ = fs::remove_dir_all(&root);
  14097     }
  14098 
  14099     #[test]
  14100     fn release_contract_discovery_does_not_search_parent_directories() {
  14101         let parent = temp_root("release_contract_parent_isolation");
  14102         write_file(
  14103             &release_contract_path(&parent, "1.0.0"),
  14104             "[release]\nversion = \"1.0.0\"\n\n[publish_order]\ncrates = []\n",
  14105         );
  14106         let capsule = parent.join("capsule");
  14107         fs::create_dir_all(&capsule).expect("create isolated capsule root");
  14108 
  14109         let err = resolve_release_contract_path_with_override(&capsule, "1.0.0", None)
  14110             .expect_err("parent release contract must be ignored");
  14111         assert!(err.contains(&capsule.display().to_string()));
  14112         assert!(
  14113             !err.contains(
  14114                 &release_contract_path(&parent, "1.0.0")
  14115                     .display()
  14116                     .to_string()
  14117             )
  14118         );
  14119 
  14120         let _ = fs::remove_dir_all(&parent);
  14121     }
  14122 
  14123     #[test]
  14124     fn root_release_policy_preflight_covers_classification_variants() {
  14125         let root = create_synthetic_workspace("root_release_policy_classifications");
  14126         configure_root_release_policy_workspace(&root);
  14127         write_root_release_policy(
  14128             &root,
  14129             r#"[release]
  14130 version = "1.0.0"
  14131 
  14132 [classification]
  14133 public = ["radroots_a"]
  14134 internal = ["radroots_b"]
  14135 deferred = ["radroots_c"]
  14136 retired = ["radroots_d"]
  14137 yank_only = ["radroots_e"]
  14138 
  14139 [publish_order]
  14140 crates = ["radroots_a"]
  14141 "#,
  14142         );
  14143 
  14144         let bundle = load_contract_bundle(&root).expect("load root release policy bundle");
  14145         validate_generic_contract_bundle(&bundle).expect("validate root release policy bundle");
  14146         validate_generic_release_preflight(&root).expect("validate root release policy preflight");
  14147 
  14148         let _ = fs::remove_dir_all(&root);
  14149     }
  14150 
  14151     #[test]
  14152     fn root_release_policy_reports_deferred_retired_and_yank_only_errors() {
  14153         for (label, policy_body, expected) in [
  14154             (
  14155                 "deferred",
  14156                 r#"[release]
  14157 version = "1.0.0"
  14158 
  14159 [classification]
  14160 public = ["radroots_a"]
  14161 internal = ["radroots_b"]
  14162 deferred = ["radroots_c", "radroots_c"]
  14163 retired = ["radroots_d"]
  14164 yank_only = ["radroots_e"]
  14165 
  14166 [publish_order]
  14167 crates = ["radroots_a"]
  14168 "#,
  14169                 "classification.deferred has duplicate crate radroots_c",
  14170             ),
  14171             (
  14172                 "retired",
  14173                 r#"[release]
  14174 version = "1.0.0"
  14175 
  14176 [classification]
  14177 public = ["radroots_a"]
  14178 internal = ["radroots_b"]
  14179 deferred = ["radroots_c"]
  14180 retired = [""]
  14181 yank_only = ["radroots_e"]
  14182 
  14183 [publish_order]
  14184 crates = ["radroots_a"]
  14185 "#,
  14186                 "classification.retired contains an empty crate name",
  14187             ),
  14188             (
  14189                 "yank_only",
  14190                 r#"[release]
  14191 version = "1.0.0"
  14192 
  14193 [classification]
  14194 public = ["radroots_a"]
  14195 internal = ["radroots_b"]
  14196 deferred = ["radroots_c"]
  14197 retired = ["radroots_d"]
  14198 yank_only = ["radroots_e", "radroots_e"]
  14199 
  14200 [publish_order]
  14201 crates = ["radroots_a"]
  14202 "#,
  14203                 "classification.yank_only has duplicate crate radroots_e",
  14204             ),
  14205         ] {
  14206             let root = create_synthetic_workspace(&format!("root_release_policy_{label}_error"));
  14207             configure_root_release_policy_workspace(&root);
  14208             write_root_release_policy(&root, policy_body);
  14209 
  14210             let err = validate_release_publish_policy(&root, &root.join("contracts"), "1.0.0")
  14211                 .expect_err("invalid non-public classification should fail");
  14212             assert!(err.contains(expected), "{label} err: {err}");
  14213 
  14214             let _ = fs::remove_dir_all(&root);
  14215         }
  14216     }
  14217 
  14218     #[test]
  14219     fn validate_release_preflight_reports_each_stage_error() {
  14220         let missing_contract_root = temp_root("preflight_missing_contract");
  14221         let missing_contract_err = validate_generic_release_preflight(&missing_contract_root)
  14222             .expect_err("missing contract");
  14223         assert!(missing_contract_err.contains("manifest.toml"));
  14224         let _ = fs::remove_dir_all(&missing_contract_root);
  14225 
  14226         let invalid_bundle = create_synthetic_workspace("preflight_invalid_bundle");
  14227         write_file(
  14228             &invalid_bundle.join("contracts").join("manifest.toml"),
  14229             r#"[contract]
  14230 name = "radroots_contract"
  14231 version = "1.0.0"
  14232 source = "synthetic"
  14233 
  14234 [surface]
  14235 model_crates = ["radroots_a"]
  14236 algorithm_crates = ["radroots_b"]
  14237 
  14238 [policy]
  14239 exclude_internal_workspace_crates = false
  14240 require_reproducible_exports = true
  14241 require_conformance_vectors = true
  14242 "#,
  14243         );
  14244         let invalid_bundle_err =
  14245             validate_generic_release_preflight(&invalid_bundle).expect_err("bundle validation");
  14246         assert!(invalid_bundle_err.contains("contract policy flags must all be true"));
  14247         let _ = fs::remove_dir_all(&invalid_bundle);
  14248 
  14249         let missing_release = create_synthetic_workspace("preflight_missing_release");
  14250         let _ = fs::remove_file(root_release_policy_path(&missing_release));
  14251         let missing_release_err =
  14252             validate_generic_release_preflight(&missing_release).expect_err("missing release");
  14253         assert!(missing_release_err.contains(RELEASE_POLICY_RELATIVE));
  14254         let _ = fs::remove_dir_all(&missing_release);
  14255 
  14256         let missing_required = create_synthetic_workspace("preflight_missing_required");
  14257         let _ = fs::remove_file(missing_required.join("contracts").join("coverage.toml"));
  14258         let missing_required_err = validate_generic_release_preflight(&missing_required)
  14259             .expect_err("missing required list");
  14260         assert!(missing_required_err.contains("coverage.toml"));
  14261         let _ = fs::remove_dir_all(&missing_required);
  14262 
  14263         let duplicate_publish = create_synthetic_workspace("preflight_duplicate_publish");
  14264         write_file(
  14265             &root_release_policy_path(&duplicate_publish),
  14266             r#"[release]
  14267 version = "1.0.0"
  14268 
  14269 [publish]
  14270 crates = ["radroots_a", "radroots_a"]
  14271 
  14272 [internal]
  14273 crates = ["radroots_b"]
  14274 
  14275 [publish_order]
  14276 crates = ["radroots_a"]
  14277 "#,
  14278         );
  14279         let duplicate_publish_err = validate_generic_release_preflight(&duplicate_publish)
  14280             .expect_err("duplicate publish crates");
  14281         assert!(duplicate_publish_err.contains("publish.crates has duplicate crate"));
  14282         let _ = fs::remove_dir_all(&duplicate_publish);
  14283 
  14284         let duplicate_required = create_synthetic_workspace("preflight_duplicate_required");
  14285         write_file(
  14286             &duplicate_required.join("contracts").join("coverage.toml"),
  14287             "[gate]\nfail_under_exec_lines = 100.0\nfail_under_functions = 100.0\nfail_under_regions = 100.0\nfail_under_branches = 100.0\nrequire_branches = true\n\n[required]\ncrates = [\"radroots_a\", \"radroots_a\"]\n",
  14288         );
  14289         let duplicate_required_err = validate_generic_release_preflight(&duplicate_required)
  14290             .expect_err("duplicate required crates");
  14291         assert!(duplicate_required_err.contains("duplicate crate"));
  14292         let _ = fs::remove_dir_all(&duplicate_required);
  14293 
  14294         let publish_metadata = create_synthetic_workspace("preflight_publish_metadata");
  14295         write_file(
  14296             &publish_metadata.join("crates").join("a").join("Cargo.toml"),
  14297             r#"[package]
  14298 name = "radroots_a"
  14299 publish = ["crates-io"]
  14300 version = "1.0.0"
  14301 edition = "2024"
  14302 "#,
  14303         );
  14304         let publish_metadata_err = validate_generic_release_preflight(&publish_metadata)
  14305             .expect_err("publish metadata validation");
  14306         assert!(publish_metadata_err.contains("must define a non-empty package.description"));
  14307         let _ = fs::remove_dir_all(&publish_metadata);
  14308 
  14309         let missing_coverage_row = create_synthetic_workspace("preflight_missing_coverage_row");
  14310         write_file(
  14311             &missing_coverage_row
  14312                 .join("target")
  14313                 .join("coverage")
  14314                 .join("coverage-refresh.tsv"),
  14315             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\n",
  14316         );
  14317         let missing_coverage_row_err = validate_generic_release_preflight(&missing_coverage_row)
  14318             .expect_err("required coverage refresh row missing");
  14319         assert!(missing_coverage_row_err.contains("missing from coverage-refresh.tsv"));
  14320         let _ = fs::remove_dir_all(&missing_coverage_row);
  14321     }
  14322 
  14323     #[test]
  14324     fn load_contract_bundle_and_validation_report_version_core_and_coverage_errors() {
  14325         let root = create_synthetic_workspace("bundle_version_core_and_coverage_errors");
  14326         write_file(&root.join("contracts").join("version.toml"), "[contract");
  14327         let version_parse_err = load_contract_bundle(&root).expect_err("invalid version file");
  14328         assert!(version_parse_err.contains("version.toml"));
  14329 
  14330         write_file(
  14331             &root.join("contracts").join("version.toml"),
  14332             r#"[contract]
  14333 version = "1.0.0"
  14334 stability = "alpha"
  14335 
  14336 [semver]
  14337 major_on = ["breaking"]
  14338 minor_on = ["feature"]
  14339 patch_on = ["fix"]
  14340 
  14341 [release_integrity]
  14342 requires_conformance_pass = true
  14343 requires_contract_manifest_diff = true
  14344 requires_release_notes = true
  14345 "#,
  14346         );
  14347         let bundle = load_contract_bundle(&root).expect("load bundle");
  14348         write_file(
  14349             &root.join("crates").join("core").join("src").join("unit.rs"),
  14350             r#"pub enum UnitDimension {
  14351 Mass,
  14352 Count,
  14353 Volume,
  14354 }
  14355 "#,
  14356         );
  14357         let core_err = validate_generic_contract_bundle(&bundle).expect_err("core unit mismatch");
  14358         assert!(core_err.contains("variant order must be"));
  14359 
  14360         write_file(
  14361             &root.join("crates").join("core").join("src").join("unit.rs"),
  14362             r#"pub enum UnitDimension {
  14363 Count,
  14364 Mass,
  14365 Volume,
  14366 }
  14367 "#,
  14368         );
  14369         write_file(
  14370             &root.join("contracts").join("coverage.toml"),
  14371             r#"[gate]
  14372 fail_under_exec_lines = 90.0
  14373 fail_under_functions = 90.0
  14374 fail_under_regions = 90.0
  14375 fail_under_branches = 90.0
  14376 require_branches = false
  14377 
  14378 [required]
  14379 crates = ["radroots_a", "radroots_b"]
  14380 "#,
  14381         );
  14382         let policy_err =
  14383             validate_generic_contract_bundle(&bundle).expect_err("coverage policy validation");
  14384         assert!(policy_err.contains("90/90/90/90"));
  14385 
  14386         let _ = fs::remove_dir_all(&root);
  14387     }
  14388 
  14389     #[test]
  14390     fn coverage_summary_and_core_enum_additional_error_paths() {
  14391         let coverage_root = temp_root("coverage_summary_additional_errors");
  14392         write_file(
  14393             &coverage_root
  14394                 .join("target")
  14395                 .join("coverage")
  14396                 .join("coverage-refresh.tsv"),
  14397             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100\tbad\t100\t100\tfile\n",
  14398         );
  14399         let func_err = load_coverage_refresh_rows(&coverage_root).expect_err("func parse error");
  14400         assert!(func_err.contains("parse func"));
  14401         write_file(
  14402             &coverage_root
  14403                 .join("target")
  14404                 .join("coverage")
  14405                 .join("coverage-refresh.tsv"),
  14406             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100\t100\tbad\t100\tfile\n",
  14407         );
  14408         let branch_err =
  14409             load_coverage_refresh_rows(&coverage_root).expect_err("branch parse error");
  14410         assert!(branch_err.contains("parse branch"));
  14411         let _ = fs::remove_dir_all(&coverage_root);
  14412 
  14413         let missing_refresh_root = temp_root("coverage_summary_missing_refresh");
  14414         let required = ["radroots_a".to_string()]
  14415             .into_iter()
  14416             .collect::<BTreeSet<_>>();
  14417         let missing_refresh_err = validate_required_coverage_summary(
  14418             &missing_refresh_root,
  14419             &required,
  14420             required_thresholds(),
  14421         )
  14422         .expect_err("missing refresh should fail");
  14423         assert!(missing_refresh_err.contains("coverage-refresh.tsv"));
  14424         let _ = fs::remove_dir_all(&missing_refresh_root);
  14425 
  14426         let enum_root = temp_root("core_unit_missing_enum");
  14427         write_file(
  14428             &enum_root
  14429                 .join("crates")
  14430                 .join("core")
  14431                 .join("src")
  14432                 .join("unit.rs"),
  14433             "pub struct NotTheEnum;",
  14434         );
  14435         let enum_err =
  14436             validate_core_unit_dimension_variant_order(&enum_root).expect_err("missing enum");
  14437         assert!(enum_err.contains("missing enum"));
  14438         let _ = fs::remove_dir_all(&enum_root);
  14439     }
  14440 
  14441     #[test]
  14442     fn publish_metadata_and_coverage_refresh_report_missing_paths() {
  14443         let root = temp_root("publish_missing_manifest");
  14444         write_file(
  14445             &root.join("Cargo.toml"),
  14446             r#"[workspace]
  14447 members = ["crates/a"]
  14448 "#,
  14449         );
  14450         write_file(
  14451             &root.join("crates").join("a").join("Cargo.toml"),
  14452             r#"[package]
  14453 name = "radroots_a"
  14454 version = "1.0.0"
  14455 edition = "2024"
  14456 authors = ["Radroots Test"]
  14457 rust-version = "1.97"
  14458 license = "MIT OR Apache-2.0"
  14459 description = "crate a"
  14460 repository = { workspace = true }
  14461 homepage = { workspace = true }
  14462 readme = { workspace = true }
  14463 "#,
  14464         );
  14465         let missing_manifest = ["radroots_b".to_string()]
  14466             .into_iter()
  14467             .collect::<BTreeSet<_>>();
  14468         let missing_err = validate_publish_package_metadata(&root, &missing_manifest)
  14469             .expect_err("missing workspace manifest");
  14470         assert!(missing_err.contains("has no workspace manifest"));
  14471 
  14472         let missing_field = ["radroots_a".to_string()]
  14473             .into_iter()
  14474             .collect::<BTreeSet<_>>();
  14475         let field_err = validate_publish_package_metadata(&root, &missing_field)
  14476             .expect_err("missing configured field");
  14477         assert!(field_err.contains("must configure package.documentation"));
  14478 
  14479         let refresh_missing =
  14480             load_coverage_refresh_rows(&root).expect_err("missing coverage-refresh.tsv");
  14481         assert!(refresh_missing.contains("coverage-refresh.tsv"));
  14482         let _ = fs::remove_dir_all(&root);
  14483     }
  14484 
  14485     #[test]
  14486     fn coverage_refresh_parser_skips_blank_lines() {
  14487         let root = temp_root("coverage_refresh_blank_lines");
  14488         write_file(
  14489             &root
  14490                 .join("target")
  14491                 .join("coverage")
  14492                 .join("coverage-refresh.tsv"),
  14493             "crate\tstatus\texec\tfunc\tbranch\tregion\treport\n\nradroots_a\tpass\t100\t100\t100\t100\tfile\n",
  14494         );
  14495         let rows = load_coverage_refresh_rows(&root).expect("rows");
  14496         assert_eq!(rows.len(), 1);
  14497         assert!(rows.contains_key("radroots_a"));
  14498         let _ = fs::remove_dir_all(&root);
  14499     }
  14500 
  14501     #[test]
  14502     fn core_unit_dimension_validation_reports_missing_and_mismatch() {
  14503         let missing = temp_root("core_unit_missing");
  14504         let missing_err = validate_core_unit_dimension_variant_order(&missing)
  14505             .expect_err("missing unit file should fail");
  14506         assert!(missing_err.contains("unit.rs"));
  14507         let _ = fs::remove_dir_all(&missing);
  14508 
  14509         let mismatch = temp_root("core_unit_mismatch");
  14510         write_file(
  14511             &mismatch
  14512                 .join("crates")
  14513                 .join("core")
  14514                 .join("src")
  14515                 .join("unit.rs"),
  14516             r#"pub enum UnitDimension {
  14517 Mass,
  14518 Count,
  14519 Volume,
  14520 }
  14521 "#,
  14522         );
  14523         let mismatch_err = validate_core_unit_dimension_variant_order(&mismatch)
  14524             .expect_err("mismatched enum order should fail");
  14525         assert!(mismatch_err.contains("variant order must be"));
  14526         let _ = fs::remove_dir_all(&mismatch);
  14527     }
  14528 
  14529     #[test]
  14530     fn coverage_and_release_additional_error_branches_are_reported() {
  14531         let root = create_synthetic_workspace("coverage_release_extra_errors");
  14532         let contract_root = root.join("contracts");
  14533         let coverage_root = coverage_root(&contract_root);
  14534         let release_policy_path = root_release_policy_path(&root);
  14535 
  14536         write_file(
  14537             &coverage_root.join("coverage.toml"),
  14538             r#"[gate]
  14539 fail_under_exec_lines = 90.0
  14540 fail_under_functions = 90.0
  14541 fail_under_regions = 90.0
  14542 fail_under_branches = 90.0
  14543 require_branches = true
  14544 
  14545 [required]
  14546 crates = ["radroots_a", "radroots_b", "radroots_extra"]
  14547 "#,
  14548         );
  14549         let coverage_extra = validate_coverage_policy_parity(&root, &contract_root)
  14550             .expect_err("coverage unknown crate");
  14551         assert!(coverage_extra.contains("includes excluded or unknown crates"));
  14552 
  14553         write_file(
  14554             &coverage_root.join("coverage.toml"),
  14555             r#"[gate]
  14556 fail_under_exec_lines = 90.0
  14557 fail_under_functions = 90.0
  14558 fail_under_regions = 90.0
  14559 fail_under_branches = 90.0
  14560 require_branches = true
  14561 
  14562 [required]
  14563 crates = ["radroots_b"]
  14564 "#,
  14565         );
  14566         let required_list_mismatch = validate_coverage_policy_parity(&root, &contract_root)
  14567             .expect_err("required list must match workspace crates");
  14568         assert!(required_list_mismatch.contains("missing workspace crates"));
  14569 
  14570         write_file(
  14571             &release_policy_path,
  14572             r#"[release]
  14573 version = "1.0.0"
  14574 
  14575 [publish]
  14576 crates = ["radroots_a", "radroots_b", "radroots_extra"]
  14577 
  14578 [internal]
  14579 crates = []
  14580 
  14581 [publish_order]
  14582 crates = ["radroots_a", "radroots_b"]
  14583 "#,
  14584         );
  14585         let release_extra = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14586             .expect_err("release extra crate");
  14587         assert!(release_extra.contains("include unknown crates"));
  14588 
  14589         write_file(
  14590             &release_policy_path,
  14591             r#"[release]
  14592 version = "1.0.0"
  14593 
  14594 [publish]
  14595 crates = ["radroots_a"]
  14596 
  14597 [internal]
  14598 crates = ["radroots_b"]
  14599 
  14600 [publish_order]
  14601 crates = ["radroots_a", "radroots_b"]
  14602 "#,
  14603         );
  14604         let publish_order_extra = validate_release_publish_policy(&root, &contract_root, "1.0.0")
  14605             .expect_err("publish order non-publish crate");
  14606         assert!(publish_order_extra.contains("non-publish crates"));
  14607 
  14608         let _ = fs::remove_dir_all(&root);
  14609     }
  14610 
  14611     #[test]
  14612     fn validate_contract_bundle_reports_release_policy_errors() {
  14613         let release_error_root = create_synthetic_workspace("bundle_release_policy_error");
  14614         write_file(
  14615             &root_release_policy_path(&release_error_root),
  14616             r#"[release]
  14617 version = "1.0.0"
  14618 
  14619 [publish]
  14620 crates = ["radroots_a"]
  14621 
  14622 [internal]
  14623 crates = ["radroots_b"]
  14624 
  14625 [publish_order]
  14626 crates = []
  14627 "#,
  14628         );
  14629         let bundle = load_contract_bundle(&release_error_root).expect("load release error bundle");
  14630         let release_err =
  14631             validate_generic_contract_bundle(&bundle).expect_err("release policy failure");
  14632         assert!(release_err.contains("publish_order.crates is missing publish crates"));
  14633         let _ = fs::remove_dir_all(&release_error_root);
  14634     }
  14635 }