lib

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

commit 11946bd7cc53d4a1f63382df2a0bd85c8d62e686
parent 48951ece71b93f58870a121f1ed9da5f701d5875
Author: triesap <tyson@radroots.org>
Date:   Mon, 27 Jul 2026 09:09:59 +0000

workspace: normalize public package metadata

- define a public 0.1.0 metadata source without coupling runtime versions
- enforce canonical package metadata and publication freeze invariants
- align the Nix toolchain and clean source closure with Rust 1.97.1
- format synchronized architecture data and regenerate governed artifacts

Diffstat:
MCargo.toml | 6++++++
Mbuild/nix/common.nix | 4++++
Mcrates/event_store/contracts/source_maintenance_v1.manifest.json | 6+++---
Mcrates/event_store/contracts/source_maintenance_v1.manifest.sha256 | 2+-
Mcrates/event_store/src/generated/source_maintenance_manifest.rs | 4++--
Mdocs/specs/radroots_crates_release_v1.sha256 | 2+-
Mdocs/specs/radroots_crates_release_v1.toml | 394+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mflake.lock | 6+++---
Mtools/xtask/src/architecture.rs | 353+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mtools/xtask/src/contract/nip09_reconciliation.rs | 18+++++++++---------
10 files changed, 722 insertions(+), 73 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -62,6 +62,12 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/radrootslabs/lib" homepage = "https://radroots.org" readme = "README" +authors = ["Tyson Lupul <tyson@radroots.org>"] + +[workspace.metadata.radroots.public-package] +version = "0.1.0" +authors = ["Tyson Lupul <tyson@radroots.org>"] +readme = "README.md" [workspace.dependencies] dto_bindgen = { version = "0.1.0" } diff --git a/build/nix/common.nix b/build/nix/common.nix @@ -20,11 +20,15 @@ let ../../Cargo.toml ../../Cargo.lock ../../CHANGELOG.md + ../../LICENSE-APACHE + ../../LICENSE-MIT ../../README ../../dto_bindgen.toml ../../rust-toolchain.toml ../../contracts ../../crates + ../../docs/implementation + ../../docs/specs ../../tools ] ); diff --git a/crates/event_store/contracts/source_maintenance_v1.manifest.json b/crates/event_store/contracts/source_maintenance_v1.manifest.json @@ -152,8 +152,8 @@ { "role": "workspace_dependency_authority", "path": "Cargo.toml", - "byte_length": 10725, - "sha256": "989e98dbf6e0ae7d2c6c3af2ccc866fdc53180c8d35d8a573d399def0f884c1b", + "byte_length": 10904, + "sha256": "183950f5b8df2fd4f82041bccb358555aab5f064f4db7ba040fa07960f663326", "hash_algorithm": "sha256_bytes_v1" }, { @@ -244,7 +244,7 @@ "role": "transitive_predecessor_membership_governance", "path": "tools/xtask/src/contract/nip09_reconciliation.rs", "byte_length": 833937, - "sha256": "0d326a4e459b2026f7ae9fc57a9741def98a2cd1ee6fbdf89713157d964d2547", + "sha256": "ee111a10b9b51f213d7c18558aaffb3bc4054449ca585be8f8ea1a9dbd464f60", "hash_algorithm": "sha256_bytes_v1" }, { diff --git a/crates/event_store/contracts/source_maintenance_v1.manifest.sha256 b/crates/event_store/contracts/source_maintenance_v1.manifest.sha256 @@ -1 +1 @@ -d15aaec204cb911d4b3c079ecbae8c98848fcd2b9c9be08bfab350199b0358df +d7d025a79381984c9a5275c04a79edd5f10f7dc92053710fdc7974836ddc3964 diff --git a/crates/event_store/src/generated/source_maintenance_manifest.rs b/crates/event_store/src/generated/source_maintenance_manifest.rs @@ -1,8 +1,8 @@ // @generated by `cargo xtask contract source-maintenance-manifest --write`; do not edit. -pub(crate) const SOURCE_MAINTENANCE_MANIFEST_JSON: &str = "{\n \"schema_version\": 1,\n \"contract_id\": \"radroots_event_store.source_maintenance_v1\",\n \"hook_id\": \"source_maintenance_v1\",\n \"manifest_schema\": {\n \"path\": \"crates/event_store/contracts/source_maintenance_v1.manifest.schema.json\",\n \"byte_length\": 12315,\n \"sha256\": \"ad4a6c8ae9488fc8033792bc6952af04687f312901c1847d8c668a62913bb642\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"predecessor\": {\n \"hook_id\": \"food_availability_projection_v1\",\n \"manifest\": {\n \"path\": \"crates/event_store/contracts/food_availability_projection_v1.manifest.json\",\n \"byte_length\": 17455,\n \"sha256\": \"33b93a3c87ce428e8aa6f5e92643c77203d9aa006c53ce96f3562fe6d68ffd23\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n }\n },\n \"migration\": {\n \"version\": 4,\n \"name\": \"source_maintenance\",\n \"up\": {\n \"path\": \"crates/event_store/migrations/0004_source_maintenance.up.sql\",\n \"byte_length\": 19841,\n \"sha256\": \"425dc799f392b87f265a6fb81f89c4a1c7a5db8391ab0380970708cb9c66704d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"down\": {\n \"path\": \"crates/event_store/migrations/0004_source_maintenance.down.sql\",\n \"byte_length\": 5172,\n \"sha256\": \"fe44fd53c51545c08ea479b385e6781079dab70fc63da2a3c205d727a00ce860\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"schema_sha256\": \"d526d96ea02be12b4b0aed99e97cfdde17c4474ace67111506a7b900ee78b186\",\n \"catalog\": {\n \"objects\": [\n \"radroots_event_store_source_capacity_delete_guard\",\n \"radroots_event_store_source_capacity_insert_guard\",\n \"radroots_event_store_source_capacity_marker_close_guard\",\n \"radroots_event_store_source_capacity_update_guard\",\n \"radroots_event_store_source_capacity_v1\",\n \"radroots_event_store_source_generation_capacity_advance\",\n \"radroots_event_store_source_generation_capacity_guard\"\n ],\n \"replaced_objects\": [\n \"radroots_event_store_food_availability_image_delete_guard\",\n \"radroots_event_store_food_availability_projection_delete_guard\",\n \"radroots_event_store_source_rebuild_marker_insert_guard\"\n ],\n \"tables\": [\n \"radroots_event_store_source_capacity_v1\"\n ],\n \"fts5_tables\": []\n }\n },\n \"source_maintenance\": {\n \"version\": 1,\n \"event_contract_registry_version\": 7,\n \"capacity_authority_id\": \"radroots_event_store_source_capacity_v1\",\n \"accounting\": {\n \"algorithm\": \"sqlite_cast_blob_octet_sum_v1\",\n \"raw_event_columns\": [\n \"event_id\",\n \"pubkey\",\n \"tags_json\",\n \"content\",\n \"sig\",\n \"raw_json\"\n ],\n \"raw_tag_columns\": [\n \"event_id\",\n \"tag_name\",\n \"tag_value\",\n \"tag_json\"\n ],\n \"nullable_raw_tag_columns\": [\n \"tag_value\"\n ]\n },\n \"limits\": {\n \"raw_events\": 25000,\n \"raw_tags\": 250000,\n \"raw_event_text_bytes\": 67108864,\n \"raw_tag_text_bytes\": 33554432,\n \"retained_source_generations\": 8\n },\n \"reopen_validation\": {\n \"mode\": \"bounded_full_raw_recount_v1\",\n \"raw_event_rejection_scan_bound\": 25001,\n \"raw_tag_rejection_scan_bound\": 250001,\n \"generation_history_validation\": \"bounded_count_plus_active_ordinal_v1\",\n \"retained_generation_rejection_scan_bound\": 9\n },\n \"rebuild_seal\": {\n \"nip09_hook_id\": \"nip09_reconciliation_v1\",\n \"nip09_manifest_sha256\": \"74af832420ffbaa9805e89df3c0b34f126a443e1598f757e3372f407f9003b77\",\n \"food_hook_id\": \"food_availability_projection_v1\",\n \"food_manifest_sha256\": \"33b93a3c87ce428e8aa6f5e92643c77203d9aa006c53ce96f3562fe6d68ffd23\",\n \"food_scope_fingerprint_sha256\": \"8b63c5ddc48a2cc7db69295238b96d5f814dba50427c80b4d0079f061e6d3de0\",\n \"active_generation_authority\": \"radroots_event_store_source_state\",\n \"marker_close_authority\": \"radroots_event_store_source_capacity_marker_close_guard\"\n }\n },\n \"entry_points\": [\n {\n \"role\": \"migration_registry\",\n \"rust_path\": \"radroots_event_store::migrations::EVENT_STORE_MIGRATIONS[3]\"\n },\n {\n \"role\": \"migration_apply_hook\",\n \"rust_path\": \"radroots_event_store::schema::apply_migration_hook\"\n },\n {\n \"role\": \"migration_validation_hook\",\n \"rust_path\": \"radroots_event_store::schema::validate_migration_hook_state\"\n },\n {\n \"role\": \"capacity_query\",\n \"rust_path\": \"radroots_event_store::RadrootsEventStore::source_capacity_v1\"\n },\n {\n \"role\": \"raw_append_preflight\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::preflight_unique_raw_source_append_v1\"\n },\n {\n \"role\": \"raw_append_advance\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::advance_source_capacity_after_insert_v1\"\n },\n {\n \"role\": \"generation_append_preflight\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::preflight_source_generation_append_v1\"\n },\n {\n \"role\": \"generation_rebuild_bind\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::bind_source_capacity_to_generation_v1\"\n },\n {\n \"role\": \"sqlite_encoding_preflight\",\n \"rust_path\": \"radroots_event_store::store::validate_main_database_encoding\"\n },\n {\n \"role\": \"source_generation_history_rollback_guard\",\n \"rust_path\": \"radroots_event_store::schema::validate_rollback_preserves_source_generation_history\"\n },\n {\n \"role\": \"result_vector_executor\",\n \"rust_path\": \"source_maintenance_v1_result_vector\"\n }\n ],\n \"source_files\": [\n {\n \"role\": \"workspace_dependency_authority\",\n \"path\": \"Cargo.toml\",\n \"byte_length\": 10725,\n \"sha256\": \"989e98dbf6e0ae7d2c6c3af2ccc866fdc53180c8d35d8a573d399def0f884c1b\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_error_and_limits\",\n \"path\": \"crates/event_store/src/error.rs\",\n \"byte_length\": 19421,\n \"sha256\": \"4772e041cb20a4963afb2f3159804c777e2f2be61bfdb6ee267e7a7c04258972\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"generated_descriptor_registration\",\n \"path\": \"crates/event_store/src/generated.rs\",\n \"byte_length\": 144,\n \"sha256\": \"6b0a8d6f249bd4fc3f878d37cb5e418680f0f1be2d9eec2518dedf03efc47121\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"public_surface\",\n \"path\": \"crates/event_store/src/lib.rs\",\n \"byte_length\": 3844,\n \"sha256\": \"3cd9653bcb752fb3c4442d4904b98a0a6208011a9a238125b7b7073d7f4e312b\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"migration_registry\",\n \"path\": \"crates/event_store/src/migrations.rs\",\n \"byte_length\": 73585,\n \"sha256\": \"a47477d04759ec6e71d14d3d05459864eae78fce0e3c2481a1b03147f04637f7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_model_public_surface\",\n \"path\": \"crates/event_store/src/model.rs\",\n \"byte_length\": 33617,\n \"sha256\": \"79296b8f263aa06d17005795e4515f769f064ea6fd971eeb1296e1151debaf20\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_generation_rebuild_authority\",\n \"path\": \"crates/event_store/src/nip09/reconciliation_v1.rs\",\n \"byte_length\": 184407,\n \"sha256\": \"c455d40fc736e3db264f567c7809af7bd897d89be8a33dfb21667a6ef6b8d6c6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"schema_migration_and_reopen_authority\",\n \"path\": \"crates/event_store/src/schema.rs\",\n \"byte_length\": 146146,\n \"sha256\": \"93b060e80d3edd73f86208e4bf698fa9d53eaf1eeb04526c9261fb8b5726fb0d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"public_store_and_transaction_authority\",\n \"path\": \"crates/event_store/src/store.rs\",\n \"byte_length\": 394574,\n \"sha256\": \"db57dc3e35e64c7194683142fe55edba853671a829269449dd2273056dfc3a0e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"raw_ingest_capacity_authority\",\n \"path\": \"crates/event_store/src/store/protocol_reconciliation_v1.rs\",\n \"byte_length\": 30140,\n \"sha256\": \"210112eeaa6975a3b4fbb97d5c52588f8c6d8d07975e531d39737fd11235de51\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_maintenance_runtime\",\n \"path\": \"crates/event_store/src/source_maintenance_v1.rs\",\n \"byte_length\": 51756,\n \"sha256\": \"f8d5b62f0613104aa86658d5bf1baade92c7df83f00ef0cddadd734b9797afca\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"artifact_transaction_authority\",\n \"path\": \"tools/xtask/src/contract/artifact_bundle.rs\",\n \"byte_length\": 38279,\n \"sha256\": \"f326ea57b56d40135f95b6b1e15961f66eed363337180a6d12a5ea903e1a9a29\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_successor_governance\",\n \"path\": \"tools/xtask/src/contract/food_availability_projection.rs\",\n \"byte_length\": 194901,\n \"sha256\": \"01fe9546c95244b4197b3d2a6cec3d72e1f7c48f088bc93f168b5e2e4977b048\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"transitive_predecessor_membership_governance\",\n \"path\": \"tools/xtask/src/contract/nip09_reconciliation.rs\",\n \"byte_length\": 833937,\n \"sha256\": \"0d326a4e459b2026f7ae9fc57a9741def98a2cd1ee6fbdf89713157d964d2547\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_maintenance_governance\",\n \"path\": \"tools/xtask/src/contract/source_maintenance.rs\",\n \"byte_length\": 176811,\n \"sha256\": \"cc6125aaeba8d7dab83c2413ca0f1a80d6f9f26876f0117e4c8fceae156304e5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"contract_command_authority\",\n \"path\": \"tools/xtask/src/contract.rs\",\n \"byte_length\": 499596,\n \"sha256\": \"ece5990259eeacac8bb12a27e89f889f82f8641b958103a0ef97eaa6d2f66fb0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"xtask_dispatch_and_release_preflight\",\n \"path\": \"tools/xtask/src/main.rs\",\n \"byte_length\": 14364,\n \"sha256\": \"27096ad2c226c6402313621712db6af23a4fdda5117c3e732cf3a3fdf3d9b434\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n }\n ],\n \"public_api\": {\n \"inherited_predecessor_symbols\": [\n \"RADROOTS_ADDRESSABLE_TRANSITION_CURSOR_JSON_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_D_TAG_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_FEED_VERSION_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_LIMIT_MAX_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_RAW_JSON_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_SCAN_MAX_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_SCOPE_KIND_MAX_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_PROJECTION_APPLY_PAGE_LIMIT_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_PROJECTION_VERSION_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_SEARCH_QUERY_MAX_BYTES_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_SEARCH_QUERY_MAX_TERMS_V1\",\n \"RadrootsAddressableTransitionCauseV1\",\n \"RadrootsAddressableTransitionCoordinateV1\",\n \"RadrootsAddressableTransitionCursorV1\",\n \"RadrootsAddressableTransitionEventReferenceV1\",\n \"RadrootsAddressableTransitionOriginV1\",\n \"RadrootsAddressableTransitionPageV1\",\n \"RadrootsAddressableTransitionRawHeadDecisionV1\",\n \"RadrootsAddressableTransitionScopeFingerprintV1\",\n \"RadrootsAddressableTransitionScopeV1\",\n \"RadrootsAddressableTransitionV1\",\n \"RadrootsAddressableTransitionVisibilityV1\",\n \"RadrootsCurrentEventVisibilityV1\",\n \"RadrootsCurrentVisibilityDecisionV1\",\n \"RadrootsFoodAvailabilitySearchQueryV1\",\n \"RadrootsFoodAvailabilityStatusFilterV1\",\n \"RadrootsNip09SuppressionEvidenceV1\",\n \"RadrootsNip09SuppressionOutcome\",\n \"RadrootsNip09SuppressionReason\",\n \"RadrootsStoreProducedCanonicalEventV1\",\n \"RadrootsStoredFoodAvailabilityImageV1\",\n \"RadrootsStoredFoodAvailabilityV1\"\n ],\n \"added_symbols\": [\n \"RADROOTS_EVENT_STORE_RAW_EVENT_COUNT_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_EVENT_TEXT_BYTES_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_TAG_COUNT_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_TAG_TEXT_BYTES_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RETAINED_SOURCE_GENERATION_LIMIT_V1\",\n \"RadrootsEventStoreSourceCapacityResourceV1\",\n \"RadrootsEventStoreSourceCapacityV1\"\n ],\n \"methods\": [\n \"RadrootsEventStore::source_capacity_v1\",\n \"RadrootsEventStoreSourceCapacityResourceV1::as_str\",\n \"RadrootsEventStoreSourceCapacityV1::source_generation\",\n \"RadrootsEventStoreSourceCapacityV1::raw_event_count\",\n \"RadrootsEventStoreSourceCapacityV1::raw_tag_count\",\n \"RadrootsEventStoreSourceCapacityV1::raw_event_text_bytes\",\n \"RadrootsEventStoreSourceCapacityV1::raw_tag_text_bytes\",\n \"RadrootsEventStoreSourceCapacityV1::raw_high_water_seq\",\n \"RadrootsEventStoreSourceCapacityV1::retained_generation_count\",\n \"RadrootsEventStoreSourceCapacityV1::retained_generation_limit\"\n ],\n \"error_variants\": [\n \"SourceCapacityExceeded\",\n \"SourceGenerationHistoryLimitReached\",\n \"PersistedEphemeralRawEvent\",\n \"SourceCapacityStateDrift\",\n \"SqliteMainDatabaseEncodingNotUtf8\",\n \"RollbackWouldDiscardSourceGenerationHistory\"\n ],\n \"removed_symbols\": [\n \"RadrootsEventStoreReconciliationResource\",\n \"RadrootsEventStoreError::ReconciliationCapacityExceeded\"\n ],\n \"breaking_replacements\": [\n {\n \"removed\": \"RadrootsEventStoreReconciliationResource\",\n \"replacement\": \"RadrootsEventStoreSourceCapacityResourceV1\"\n },\n {\n \"removed\": \"RadrootsEventStoreError::ReconciliationCapacityExceeded\",\n \"replacement\": \"RadrootsEventStoreError::SourceCapacityExceeded\"\n }\n ]\n },\n \"result_vector\": {\n \"canonical_path\": \"contracts/conformance/vectors/event_store/source_maintenance.v1.json\",\n \"mirror_path\": \"crates/event_store/tests/fixtures/source_maintenance.v1.json\",\n \"byte_length\": 16253,\n \"sha256\": \"997aba2604a2b9d199fb87dc9d07942ca50d91863aeadcf3eeacf16d191dd71f\",\n \"hash_algorithm\": \"sha256_bytes_v1\",\n \"executor_id\": \"radroots_event_store.source_maintenance_v1.result_vector_executor.v1\",\n \"executor_path\": \"crates/event_store/tests/source_maintenance_v1_result_vector.rs\",\n \"executor_test\": \"source_maintenance_v1_result_vector\",\n \"executor_byte_length\": 23510,\n \"executor_sha256\": \"a7487afdfe19fc5fc794811d0f0e6035203e1aabcf0a33a1d398f6b3555d38f3\",\n \"executor_hash_algorithm\": \"sha256_bytes_v1\"\n }\n}\n"; +pub(crate) const SOURCE_MAINTENANCE_MANIFEST_JSON: &str = "{\n \"schema_version\": 1,\n \"contract_id\": \"radroots_event_store.source_maintenance_v1\",\n \"hook_id\": \"source_maintenance_v1\",\n \"manifest_schema\": {\n \"path\": \"crates/event_store/contracts/source_maintenance_v1.manifest.schema.json\",\n \"byte_length\": 12315,\n \"sha256\": \"ad4a6c8ae9488fc8033792bc6952af04687f312901c1847d8c668a62913bb642\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"predecessor\": {\n \"hook_id\": \"food_availability_projection_v1\",\n \"manifest\": {\n \"path\": \"crates/event_store/contracts/food_availability_projection_v1.manifest.json\",\n \"byte_length\": 17455,\n \"sha256\": \"33b93a3c87ce428e8aa6f5e92643c77203d9aa006c53ce96f3562fe6d68ffd23\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n }\n },\n \"migration\": {\n \"version\": 4,\n \"name\": \"source_maintenance\",\n \"up\": {\n \"path\": \"crates/event_store/migrations/0004_source_maintenance.up.sql\",\n \"byte_length\": 19841,\n \"sha256\": \"425dc799f392b87f265a6fb81f89c4a1c7a5db8391ab0380970708cb9c66704d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"down\": {\n \"path\": \"crates/event_store/migrations/0004_source_maintenance.down.sql\",\n \"byte_length\": 5172,\n \"sha256\": \"fe44fd53c51545c08ea479b385e6781079dab70fc63da2a3c205d727a00ce860\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n \"schema_sha256\": \"d526d96ea02be12b4b0aed99e97cfdde17c4474ace67111506a7b900ee78b186\",\n \"catalog\": {\n \"objects\": [\n \"radroots_event_store_source_capacity_delete_guard\",\n \"radroots_event_store_source_capacity_insert_guard\",\n \"radroots_event_store_source_capacity_marker_close_guard\",\n \"radroots_event_store_source_capacity_update_guard\",\n \"radroots_event_store_source_capacity_v1\",\n \"radroots_event_store_source_generation_capacity_advance\",\n \"radroots_event_store_source_generation_capacity_guard\"\n ],\n \"replaced_objects\": [\n \"radroots_event_store_food_availability_image_delete_guard\",\n \"radroots_event_store_food_availability_projection_delete_guard\",\n \"radroots_event_store_source_rebuild_marker_insert_guard\"\n ],\n \"tables\": [\n \"radroots_event_store_source_capacity_v1\"\n ],\n \"fts5_tables\": []\n }\n },\n \"source_maintenance\": {\n \"version\": 1,\n \"event_contract_registry_version\": 7,\n \"capacity_authority_id\": \"radroots_event_store_source_capacity_v1\",\n \"accounting\": {\n \"algorithm\": \"sqlite_cast_blob_octet_sum_v1\",\n \"raw_event_columns\": [\n \"event_id\",\n \"pubkey\",\n \"tags_json\",\n \"content\",\n \"sig\",\n \"raw_json\"\n ],\n \"raw_tag_columns\": [\n \"event_id\",\n \"tag_name\",\n \"tag_value\",\n \"tag_json\"\n ],\n \"nullable_raw_tag_columns\": [\n \"tag_value\"\n ]\n },\n \"limits\": {\n \"raw_events\": 25000,\n \"raw_tags\": 250000,\n \"raw_event_text_bytes\": 67108864,\n \"raw_tag_text_bytes\": 33554432,\n \"retained_source_generations\": 8\n },\n \"reopen_validation\": {\n \"mode\": \"bounded_full_raw_recount_v1\",\n \"raw_event_rejection_scan_bound\": 25001,\n \"raw_tag_rejection_scan_bound\": 250001,\n \"generation_history_validation\": \"bounded_count_plus_active_ordinal_v1\",\n \"retained_generation_rejection_scan_bound\": 9\n },\n \"rebuild_seal\": {\n \"nip09_hook_id\": \"nip09_reconciliation_v1\",\n \"nip09_manifest_sha256\": \"74af832420ffbaa9805e89df3c0b34f126a443e1598f757e3372f407f9003b77\",\n \"food_hook_id\": \"food_availability_projection_v1\",\n \"food_manifest_sha256\": \"33b93a3c87ce428e8aa6f5e92643c77203d9aa006c53ce96f3562fe6d68ffd23\",\n \"food_scope_fingerprint_sha256\": \"8b63c5ddc48a2cc7db69295238b96d5f814dba50427c80b4d0079f061e6d3de0\",\n \"active_generation_authority\": \"radroots_event_store_source_state\",\n \"marker_close_authority\": \"radroots_event_store_source_capacity_marker_close_guard\"\n }\n },\n \"entry_points\": [\n {\n \"role\": \"migration_registry\",\n \"rust_path\": \"radroots_event_store::migrations::EVENT_STORE_MIGRATIONS[3]\"\n },\n {\n \"role\": \"migration_apply_hook\",\n \"rust_path\": \"radroots_event_store::schema::apply_migration_hook\"\n },\n {\n \"role\": \"migration_validation_hook\",\n \"rust_path\": \"radroots_event_store::schema::validate_migration_hook_state\"\n },\n {\n \"role\": \"capacity_query\",\n \"rust_path\": \"radroots_event_store::RadrootsEventStore::source_capacity_v1\"\n },\n {\n \"role\": \"raw_append_preflight\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::preflight_unique_raw_source_append_v1\"\n },\n {\n \"role\": \"raw_append_advance\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::advance_source_capacity_after_insert_v1\"\n },\n {\n \"role\": \"generation_append_preflight\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::preflight_source_generation_append_v1\"\n },\n {\n \"role\": \"generation_rebuild_bind\",\n \"rust_path\": \"radroots_event_store::source_maintenance_v1::bind_source_capacity_to_generation_v1\"\n },\n {\n \"role\": \"sqlite_encoding_preflight\",\n \"rust_path\": \"radroots_event_store::store::validate_main_database_encoding\"\n },\n {\n \"role\": \"source_generation_history_rollback_guard\",\n \"rust_path\": \"radroots_event_store::schema::validate_rollback_preserves_source_generation_history\"\n },\n {\n \"role\": \"result_vector_executor\",\n \"rust_path\": \"source_maintenance_v1_result_vector\"\n }\n ],\n \"source_files\": [\n {\n \"role\": \"workspace_dependency_authority\",\n \"path\": \"Cargo.toml\",\n \"byte_length\": 10904,\n \"sha256\": \"183950f5b8df2fd4f82041bccb358555aab5f064f4db7ba040fa07960f663326\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_error_and_limits\",\n \"path\": \"crates/event_store/src/error.rs\",\n \"byte_length\": 19421,\n \"sha256\": \"4772e041cb20a4963afb2f3159804c777e2f2be61bfdb6ee267e7a7c04258972\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"generated_descriptor_registration\",\n \"path\": \"crates/event_store/src/generated.rs\",\n \"byte_length\": 144,\n \"sha256\": \"6b0a8d6f249bd4fc3f878d37cb5e418680f0f1be2d9eec2518dedf03efc47121\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"public_surface\",\n \"path\": \"crates/event_store/src/lib.rs\",\n \"byte_length\": 3844,\n \"sha256\": \"3cd9653bcb752fb3c4442d4904b98a0a6208011a9a238125b7b7073d7f4e312b\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"migration_registry\",\n \"path\": \"crates/event_store/src/migrations.rs\",\n \"byte_length\": 73585,\n \"sha256\": \"a47477d04759ec6e71d14d3d05459864eae78fce0e3c2481a1b03147f04637f7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_model_public_surface\",\n \"path\": \"crates/event_store/src/model.rs\",\n \"byte_length\": 33617,\n \"sha256\": \"79296b8f263aa06d17005795e4515f769f064ea6fd971eeb1296e1151debaf20\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_generation_rebuild_authority\",\n \"path\": \"crates/event_store/src/nip09/reconciliation_v1.rs\",\n \"byte_length\": 184407,\n \"sha256\": \"c455d40fc736e3db264f567c7809af7bd897d89be8a33dfb21667a6ef6b8d6c6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"schema_migration_and_reopen_authority\",\n \"path\": \"crates/event_store/src/schema.rs\",\n \"byte_length\": 146146,\n \"sha256\": \"93b060e80d3edd73f86208e4bf698fa9d53eaf1eeb04526c9261fb8b5726fb0d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"public_store_and_transaction_authority\",\n \"path\": \"crates/event_store/src/store.rs\",\n \"byte_length\": 394574,\n \"sha256\": \"db57dc3e35e64c7194683142fe55edba853671a829269449dd2273056dfc3a0e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"raw_ingest_capacity_authority\",\n \"path\": \"crates/event_store/src/store/protocol_reconciliation_v1.rs\",\n \"byte_length\": 30140,\n \"sha256\": \"210112eeaa6975a3b4fbb97d5c52588f8c6d8d07975e531d39737fd11235de51\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_maintenance_runtime\",\n \"path\": \"crates/event_store/src/source_maintenance_v1.rs\",\n \"byte_length\": 51756,\n \"sha256\": \"f8d5b62f0613104aa86658d5bf1baade92c7df83f00ef0cddadd734b9797afca\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"artifact_transaction_authority\",\n \"path\": \"tools/xtask/src/contract/artifact_bundle.rs\",\n \"byte_length\": 38279,\n \"sha256\": \"f326ea57b56d40135f95b6b1e15961f66eed363337180a6d12a5ea903e1a9a29\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_successor_governance\",\n \"path\": \"tools/xtask/src/contract/food_availability_projection.rs\",\n \"byte_length\": 194901,\n \"sha256\": \"01fe9546c95244b4197b3d2a6cec3d72e1f7c48f088bc93f168b5e2e4977b048\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"transitive_predecessor_membership_governance\",\n \"path\": \"tools/xtask/src/contract/nip09_reconciliation.rs\",\n \"byte_length\": 833937,\n \"sha256\": \"ee111a10b9b51f213d7c18558aaffb3bc4054449ca585be8f8ea1a9dbd464f60\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"source_maintenance_governance\",\n \"path\": \"tools/xtask/src/contract/source_maintenance.rs\",\n \"byte_length\": 176811,\n \"sha256\": \"cc6125aaeba8d7dab83c2413ca0f1a80d6f9f26876f0117e4c8fceae156304e5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"contract_command_authority\",\n \"path\": \"tools/xtask/src/contract.rs\",\n \"byte_length\": 499596,\n \"sha256\": \"ece5990259eeacac8bb12a27e89f889f82f8641b958103a0ef97eaa6d2f66fb0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"xtask_dispatch_and_release_preflight\",\n \"path\": \"tools/xtask/src/main.rs\",\n \"byte_length\": 14364,\n \"sha256\": \"27096ad2c226c6402313621712db6af23a4fdda5117c3e732cf3a3fdf3d9b434\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n }\n ],\n \"public_api\": {\n \"inherited_predecessor_symbols\": [\n \"RADROOTS_ADDRESSABLE_TRANSITION_CURSOR_JSON_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_D_TAG_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_FEED_VERSION_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_LIMIT_MAX_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_RAW_JSON_MAX_BYTES_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_PAGE_SCAN_MAX_V1\",\n \"RADROOTS_ADDRESSABLE_TRANSITION_SCOPE_KIND_MAX_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_PROJECTION_APPLY_PAGE_LIMIT_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_PROJECTION_VERSION_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_SEARCH_QUERY_MAX_BYTES_V1\",\n \"RADROOTS_FOOD_AVAILABILITY_SEARCH_QUERY_MAX_TERMS_V1\",\n \"RadrootsAddressableTransitionCauseV1\",\n \"RadrootsAddressableTransitionCoordinateV1\",\n \"RadrootsAddressableTransitionCursorV1\",\n \"RadrootsAddressableTransitionEventReferenceV1\",\n \"RadrootsAddressableTransitionOriginV1\",\n \"RadrootsAddressableTransitionPageV1\",\n \"RadrootsAddressableTransitionRawHeadDecisionV1\",\n \"RadrootsAddressableTransitionScopeFingerprintV1\",\n \"RadrootsAddressableTransitionScopeV1\",\n \"RadrootsAddressableTransitionV1\",\n \"RadrootsAddressableTransitionVisibilityV1\",\n \"RadrootsCurrentEventVisibilityV1\",\n \"RadrootsCurrentVisibilityDecisionV1\",\n \"RadrootsFoodAvailabilitySearchQueryV1\",\n \"RadrootsFoodAvailabilityStatusFilterV1\",\n \"RadrootsNip09SuppressionEvidenceV1\",\n \"RadrootsNip09SuppressionOutcome\",\n \"RadrootsNip09SuppressionReason\",\n \"RadrootsStoreProducedCanonicalEventV1\",\n \"RadrootsStoredFoodAvailabilityImageV1\",\n \"RadrootsStoredFoodAvailabilityV1\"\n ],\n \"added_symbols\": [\n \"RADROOTS_EVENT_STORE_RAW_EVENT_COUNT_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_EVENT_TEXT_BYTES_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_TAG_COUNT_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RAW_TAG_TEXT_BYTES_LIMIT_V1\",\n \"RADROOTS_EVENT_STORE_RETAINED_SOURCE_GENERATION_LIMIT_V1\",\n \"RadrootsEventStoreSourceCapacityResourceV1\",\n \"RadrootsEventStoreSourceCapacityV1\"\n ],\n \"methods\": [\n \"RadrootsEventStore::source_capacity_v1\",\n \"RadrootsEventStoreSourceCapacityResourceV1::as_str\",\n \"RadrootsEventStoreSourceCapacityV1::source_generation\",\n \"RadrootsEventStoreSourceCapacityV1::raw_event_count\",\n \"RadrootsEventStoreSourceCapacityV1::raw_tag_count\",\n \"RadrootsEventStoreSourceCapacityV1::raw_event_text_bytes\",\n \"RadrootsEventStoreSourceCapacityV1::raw_tag_text_bytes\",\n \"RadrootsEventStoreSourceCapacityV1::raw_high_water_seq\",\n \"RadrootsEventStoreSourceCapacityV1::retained_generation_count\",\n \"RadrootsEventStoreSourceCapacityV1::retained_generation_limit\"\n ],\n \"error_variants\": [\n \"SourceCapacityExceeded\",\n \"SourceGenerationHistoryLimitReached\",\n \"PersistedEphemeralRawEvent\",\n \"SourceCapacityStateDrift\",\n \"SqliteMainDatabaseEncodingNotUtf8\",\n \"RollbackWouldDiscardSourceGenerationHistory\"\n ],\n \"removed_symbols\": [\n \"RadrootsEventStoreReconciliationResource\",\n \"RadrootsEventStoreError::ReconciliationCapacityExceeded\"\n ],\n \"breaking_replacements\": [\n {\n \"removed\": \"RadrootsEventStoreReconciliationResource\",\n \"replacement\": \"RadrootsEventStoreSourceCapacityResourceV1\"\n },\n {\n \"removed\": \"RadrootsEventStoreError::ReconciliationCapacityExceeded\",\n \"replacement\": \"RadrootsEventStoreError::SourceCapacityExceeded\"\n }\n ]\n },\n \"result_vector\": {\n \"canonical_path\": \"contracts/conformance/vectors/event_store/source_maintenance.v1.json\",\n \"mirror_path\": \"crates/event_store/tests/fixtures/source_maintenance.v1.json\",\n \"byte_length\": 16253,\n \"sha256\": \"997aba2604a2b9d199fb87dc9d07942ca50d91863aeadcf3eeacf16d191dd71f\",\n \"hash_algorithm\": \"sha256_bytes_v1\",\n \"executor_id\": \"radroots_event_store.source_maintenance_v1.result_vector_executor.v1\",\n \"executor_path\": \"crates/event_store/tests/source_maintenance_v1_result_vector.rs\",\n \"executor_test\": \"source_maintenance_v1_result_vector\",\n \"executor_byte_length\": 23510,\n \"executor_sha256\": \"a7487afdfe19fc5fc794811d0f0e6035203e1aabcf0a33a1d398f6b3555d38f3\",\n \"executor_hash_algorithm\": \"sha256_bytes_v1\"\n }\n}\n"; pub(crate) const SOURCE_MAINTENANCE_MANIFEST_BYTE_LENGTH: usize = 14459; pub(crate) const SOURCE_MAINTENANCE_MANIFEST_SHA256: &str = - "d15aaec204cb911d4b3c079ecbae8c98848fcd2b9c9be08bfab350199b0358df"; + "d7d025a79381984c9a5275c04a79edd5f10f7dc92053710fdc7974836ddc3964"; pub(crate) const SOURCE_MAINTENANCE_MANIFEST_SCHEMA_VERSION: u32 = 1; pub(crate) const SOURCE_MAINTENANCE_CONTRACT_ID: &str = "radroots_event_store.source_maintenance_v1"; diff --git a/docs/specs/radroots_crates_release_v1.sha256 b/docs/specs/radroots_crates_release_v1.sha256 @@ -1,4 +1,4 @@ 8ddb51b5f186cb7ebcd7d2cd60217dce183ad9c87d7363f91fbaa6ff8db9777e radroots_crates_release_v1.md -f1f6661da8cec1bb1128b4f2846d4c2c0d97f391cb458003ced7296074c7bc9f radroots_crates_release_v1.toml +a9dfec76ec11a1f1817133b0ad40dc062df3b2b5f77c3c96eeb92f0eff718aa7 radroots_crates_release_v1.toml 6e4a1c00d762e36e18e530d8e88846d500aeb8889d6f36d7ef906a055ef30a37 radroots_crates_release_v1_inventory.csv dc5a24247df8feb6bad11985475cd3ccb5b7740a0dce8ad5198f47da7aff3480 radroots_crates_release_v1.dot diff --git a/docs/specs/radroots_crates_release_v1.toml b/docs/specs/radroots_crates_release_v1.toml @@ -64,8 +64,25 @@ default_features = ["std", "serde"] features = ["std", "serde"] required_radroots_dependencies = [] optional_radroots_dependencies = [] -modules = ["currency", "decimal", "money", "percent", "pricing", "quantity", "unit"] -root_exports = ["Currency", "Decimal", "Money", "Percent", "Quantity", "QuantityPrice", "Unit", "Error"] +modules = [ + "currency", + "decimal", + "money", + "percent", + "pricing", + "quantity", + "unit", +] +root_exports = [ + "Currency", + "Decimal", + "Money", + "Percent", + "Quantity", + "QuantityPrice", + "Unit", + "Error", +] forbidden = "Identifiers, identities, event kinds, networking, persistence, clocks, filesystem paths, process behavior, or application configuration." [[package]] @@ -80,7 +97,15 @@ features = ["std", "serde"] required_radroots_dependencies = [] optional_radroots_dependencies = [] modules = ["account", "key", "profile", "username"] -root_exports = ["AccountId", "IdentityId", "PublicIdentity", "PublicKey", "Profile", "Username", "Error"] +root_exports = [ + "AccountId", + "IdentityId", + "PublicIdentity", + "PublicKey", + "Profile", + "Username", + "Error", +] forbidden = "Secret keys, key generation, NIP-49 encryption, keyrings, files, SQLite, runtime paths, upstream nostr::Event values, signer sessions, or host account selection." [[package]] @@ -95,7 +120,15 @@ features = ["std", "serde"] required_radroots_dependencies = [] optional_radroots_dependencies = [] modules = ["authorization", "descriptor", "hash", "media_type", "url"] -root_exports = ["BlobUrl", "Sha256", "MediaType", "BlobDescriptor", "ByteVerifiedDescriptor", "AuthorizationClaim", "Error"] +root_exports = [ + "BlobUrl", + "Sha256", + "MediaType", + "BlobDescriptor", + "ByteVerifiedDescriptor", + "AuthorizationClaim", + "Error", +] forbidden = "HTTP clients, upload scheduling, cache management, filesystem traversal, application media policy, or global authentication state." [[package]] @@ -109,7 +142,14 @@ default_features = ["std", "serde"] features = ["std", "serde"] required_radroots_dependencies = [] optional_radroots_dependencies = [] -modules = ["capability::v1", "error::v1", "event::v1", "runtime::v1", "radrootsd::transport_publish::v5", "schema"] +modules = [ + "capability::v1", + "error::v1", + "event::v1", + "runtime::v1", + "radrootsd::transport_publish::v5", + "schema", +] root_exports = [] forbidden = "Native clients, storage, network I/O, executor/runtime ownership, domain reducers, upstream dependency types, unversioned serialized DTOs, or package names containing protocol generations." @@ -122,10 +162,42 @@ platform = "no_std + alloc; std feature" responsibility = "Canonical Radroots event-domain models, validated event identifiers, tags, event contracts, authoring drafts, signed/verified typestates, and NIP-01 wire-neutral representations." default_features = ["std", "serde"] features = ["std", "serde", "knowledge"] -required_radroots_dependencies = ["radroots-core", "radroots-identity", "radroots-blossom", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-core", + "radroots-identity", + "radroots-blossom", + "radroots-protocol", +] optional_radroots_dependencies = [] -modules = ["admission", "calendar", "contract", "draft", "envelope", "farm", "food", "id", "knowledge", "listing", "media", "post", "profile", "social", "tag", "trade", "wire"] -root_exports = ["Event", "EventDraft", "SignedEvent", "VerifiedEvent", "EventId", "EventKind", "EventTag", "Error"] +modules = [ + "admission", + "calendar", + "contract", + "draft", + "envelope", + "farm", + "food", + "id", + "knowledge", + "listing", + "media", + "post", + "profile", + "social", + "tag", + "trade", + "wire", +] +root_exports = [ + "Event", + "EventDraft", + "SignedEvent", + "VerifiedEvent", + "EventId", + "EventKind", + "EventTag", + "Error", +] forbidden = "Live Nostr clients, relay pools, signing backends, SQLite, outbox claims, retry scheduling, application state, or duplicate trade/order identifier concepts." [[package]] @@ -137,7 +209,11 @@ platform = "no_std + alloc where selected features permit; std feature" responsibility = "Deterministic canonical encoding, decoding, ID/signature verification, contract validation, admission, and manifest generation for Radroots events." default_features = ["std", "json"] features = ["std", "serde", "json", "knowledge", "manifests"] -required_radroots_dependencies = ["radroots-event", "radroots-blossom", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-event", + "radroots-blossom", + "radroots-protocol", +] optional_radroots_dependencies = [] modules = ["admission", "canonical", "decode", "encode", "manifest", "verify"] root_exports = ["Codec", "DecodeError", "EncodeError", "VerificationError"] @@ -152,10 +228,21 @@ platform = "no_std + alloc for model/reducer; std feature" responsibility = "Trade validation, evidence models, deterministic reduction, conflict analysis, and side-effect-free workflow plans over the canonical event trade model." default_features = ["std", "serde", "json"] features = ["std", "serde", "json"] -required_radroots_dependencies = ["radroots-core", "radroots-identity", "radroots-event"] +required_radroots_dependencies = [ + "radroots-core", + "radroots-identity", + "radroots-event", +] optional_radroots_dependencies = [] modules = ["evidence", "model", "reducer", "validation", "workflow"] -root_exports = ["Projection", "ReductionInput", "ReducerIssue", "WorkflowPlan", "ValidationError", "Error"] +root_exports = [ + "Projection", + "ReductionInput", + "ReducerIssue", + "WorkflowPlan", + "ValidationError", + "Error", +] forbidden = "A second TradeId definition, actor authorization, signers, event-store access, SQLx, filesystem state, transport delivery, outbox mutation, or process scheduling." [[package]] @@ -167,10 +254,29 @@ platform = "no_std + alloc core; std feature" responsibility = "Object-safe author/signing SPI, actor provenance, authorization checks, requests, receipts, progress, capabilities, and normalized signing errors." default_features = ["std", "serde"] features = ["std", "serde"] -required_radroots_dependencies = ["radroots-identity", "radroots-event", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-identity", + "radroots-event", + "radroots-protocol", +] optional_radroots_dependencies = [] -modules = ["actor", "capability", "error", "request", "receipt", "signer", "status"] -root_exports = ["Actor", "Signer", "SignRequest", "SignReceipt", "SignerStatus", "Error"] +modules = [ + "actor", + "capability", + "error", + "request", + "receipt", + "signer", + "status", +] +root_exports = [ + "Actor", + "Signer", + "SignRequest", + "SignReceipt", + "SignerStatus", + "Error", +] forbidden = "Raw secret-key ownership, keyrings, relay networking, NIP-46 session persistence, SQL, UI prompts, or executor creation." [[package]] @@ -182,10 +288,34 @@ platform = "no_std + alloc data model; std feature" responsibility = "Transport-neutral target identities, capability/status models, source and sink SPIs, delivery/fetch policies, bounded requests, provenance, and normalized outcomes." default_features = ["std", "serde"] features = ["std", "serde"] -required_radroots_dependencies = ["radroots-identity", "radroots-event", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-identity", + "radroots-event", + "radroots-protocol", +] optional_radroots_dependencies = [] -modules = ["capability", "endpoint", "error", "outcome", "policy", "sink", "source", "target"] -root_exports = ["TransportId", "Target", "TargetSet", "EventSource", "EventSink", "DeliveryRequest", "DeliveryReceipt", "FetchRequest", "FetchPage", "Error"] +modules = [ + "capability", + "endpoint", + "error", + "outcome", + "policy", + "sink", + "source", + "target", +] +root_exports = [ + "TransportId", + "Target", + "TargetSet", + "EventSource", + "EventSink", + "DeliveryRequest", + "DeliveryReceipt", + "FetchRequest", + "FetchPage", + "Error", +] forbidden = "Closed enums that prevent new transports, Reticulum-specific constants, Nostr URLs at the generic root, storage/outbox access, retries, scheduler ownership, or silent fallback." [[package]] @@ -197,7 +327,11 @@ platform = "no_std + alloc for conversion surface; std feature" responsibility = "Portable conversion between Radroots native event/identity types and Nostr protocol types, typed NIP helpers, and concrete local signing adapters; no live relay client." default_features = ["std", "events"] features = ["std", "events", "signing", "nip17", "blossom"] -required_radroots_dependencies = ["radroots-identity", "radroots-event", "radroots-event-codec"] +required_radroots_dependencies = [ + "radroots-identity", + "radroots-event", + "radroots-event-codec", +] optional_radroots_dependencies = ["radroots-signing", "radroots-blossom"] modules = ["blossom", "event", "filter", "key", "nip17", "signing", "tag"] root_exports = ["Error"] @@ -212,10 +346,33 @@ platform = "std for v1; protocol data kept portable" responsibility = "Nostr Connect/NIP-46 URIs, methods, permissions, requests, responses, client/server state machines, timeout-independent protocol validation, and normalized errors." default_features = ["serde"] features = ["serde"] -required_radroots_dependencies = ["radroots-identity", "radroots-event", "radroots-nostr", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-identity", + "radroots-event", + "radroots-nostr", + "radroots-protocol", +] optional_radroots_dependencies = [] -modules = ["client", "error", "message", "method", "permission", "server", "uri"] -root_exports = ["Client", "Server", "Method", "Permission", "Request", "Response", "BunkerUri", "ClientUri", "Error"] +modules = [ + "client", + "error", + "message", + "method", + "permission", + "server", + "uri", +] +root_exports = [ + "Client", + "Server", + "Method", + "Permission", + "Request", + "Response", + "BunkerUri", + "ClientUri", + "Error", +] forbidden = "Relay-pool implementation, secret persistence, approval UI, global sessions, Tokio runtime ownership, or Myc-specific service storage." [[package]] @@ -229,8 +386,24 @@ default_features = ["std", "serde"] features = ["std", "serde", "memory", "file", "keyring"] required_radroots_dependencies = [] optional_radroots_dependencies = [] -modules = ["envelope", "error", "id", "provider", "wrapping", "memory", "file", "keyring"] -root_exports = ["SecretId", "SecretRef", "SecretProvider", "KeyWrapping", "EncryptedEnvelope", "Error"] +modules = [ + "envelope", + "error", + "id", + "provider", + "wrapping", + "memory", + "file", + "keyring", +] +root_exports = [ + "SecretId", + "SecretRef", + "SecretProvider", + "KeyWrapping", + "EncryptedEnvelope", + "Error", +] forbidden = "Public secret bytes, Clone/Debug/Serialize for secret-bearing values, identity profiles, domain tables, arbitrary key/value storage, hidden key generation, or process-global vaults." [[package]] @@ -242,10 +415,34 @@ platform = "std for v1" responsibility = "Backend-neutral canonical event, operation journal, outbox, transport evidence, projection, private-artifact metadata, backup, status, and atomic commit interfaces, plus an in-memory reference backend." default_features = ["memory", "serde"] features = ["memory", "serde"] -required_radroots_dependencies = ["radroots-event", "radroots-trade", "radroots-transport", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-event", + "radroots-trade", + "radroots-transport", + "radroots-protocol", +] optional_radroots_dependencies = [] -modules = ["atomic", "backup", "event", "journal", "memory", "outbox", "private_artifact", "projection", "status"] -root_exports = ["Storage", "EventStore", "Journal", "Outbox", "ProjectionStore", "BackupSource", "StorageStatus", "Error"] +modules = [ + "atomic", + "backup", + "event", + "journal", + "memory", + "outbox", + "private_artifact", + "projection", + "status", +] +root_exports = [ + "Storage", + "EventStore", + "Journal", + "Outbox", + "ProjectionStore", + "BackupSource", + "StorageStatus", + "Error", +] forbidden = "SQL text, SQLx pools or transactions, filesystem paths, application UI state, concrete retry loops, Nostr clients, or unconstrained raw key/value escape hatches." [[package]] @@ -257,9 +454,21 @@ platform = "std-only native backend" responsibility = "SQLite implementation of the storage SPIs with schema migration, WAL, locking, integrity, backup/restore, crash recovery, and encrypted private storage." default_features = [] features = [] -required_radroots_dependencies = ["radroots-storage", "radroots-event-codec", "radroots-secrets"] +required_radroots_dependencies = [ + "radroots-storage", + "radroots-event-codec", + "radroots-secrets", +] optional_radroots_dependencies = [] -modules = ["backup", "config", "integrity", "lock", "migration", "open", "status"] +modules = [ + "backup", + "config", + "integrity", + "lock", + "migration", + "open", + "status", +] root_exports = ["SqliteStorage", "OpenOptions", "OpenMode", "Paths", "Error"] forbidden = "Public SqlitePool/Connection/Transaction handles, caller-supplied arbitrary SQL, Studio state, global connection pools, runtime installation, or silent schema downgrade." @@ -272,10 +481,21 @@ platform = "std-only; Tokio implementation detail in v1" responsibility = "Concrete Nostr EventSource/EventSink implementation: relay URL policy, connection, NIP-42 authentication, bounded fetch pages, delivery, status, and relay-outcome normalization." default_features = [] features = [] -required_radroots_dependencies = ["radroots-transport", "radroots-nostr", "radroots-event-codec", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-transport", + "radroots-nostr", + "radroots-event-codec", + "radroots-protocol", +] optional_radroots_dependencies = [] modules = ["auth", "client", "relay", "sink", "source", "status"] -root_exports = ["NostrTransport", "Config", "RelayUrl", "RelayUrlPolicy", "Error"] +root_exports = [ + "NostrTransport", + "Config", + "RelayUrl", + "RelayUrlPolicy", + "Error", +] forbidden = "Event-store ingestion, outbox claiming, retry scheduling, projection refresh, global relay clients, direct SQL, or transport fallback." [[package]] @@ -287,10 +507,26 @@ platform = "std-only in v1; executor-neutral public API" responsibility = "Shared pull, verification, canonical admission, duplicate handling, projection refresh, outbox signing/delivery, status, and retry-decision orchestration without owning scheduling." default_features = ["serde"] features = ["serde"] -required_radroots_dependencies = ["radroots-event", "radroots-event-codec", "radroots-signing", "radroots-transport", "radroots-storage", "radroots-trade", "radroots-protocol"] +required_radroots_dependencies = [ + "radroots-event", + "radroots-event-codec", + "radroots-signing", + "radroots-transport", + "radroots-storage", + "radroots-trade", + "radroots-protocol", +] optional_radroots_dependencies = [] modules = ["ingest", "policy", "projection", "pull", "push", "status"] -root_exports = ["Engine", "PullRequest", "PullReceipt", "PushRequest", "PushReceipt", "SyncStatus", "Error"] +root_exports = [ + "Engine", + "PullRequest", + "PullReceipt", + "PushRequest", + "PushReceipt", + "SyncStatus", + "Error", +] forbidden = "Creating an executor, spawning hidden workers, installing timers globally, owning process lifecycle, storing UI state, or transport-specific branches outside adapters." [[package]] @@ -305,7 +541,15 @@ features = [] required_radroots_dependencies = [] optional_radroots_dependencies = [] modules = ["asset", "database", "download", "model", "query"] -root_exports = ["Geocoder", "AssetSpec", "AssetStatus", "Query", "Candidate", "Point", "Error"] +root_exports = [ + "Geocoder", + "AssetSpec", + "AssetStatus", + "Query", + "Candidate", + "Point", + "Error", +] forbidden = "Generic multi-provider abstraction before a second provider exists, runtime-path policy, hidden downloads, SDK configuration types, SQLx/reqwest types in the public API, or test-fixture features." [[package]] @@ -316,10 +560,52 @@ tier = "advanced front door" platform = "std-only native engine" responsibility = "Host-neutral asynchronous client engine, product operations, capability reporting, explicit storage/signing/transport composition, diagnostics, backup/restore, and safe commit semantics." default_features = ["memory"] -features = ["memory", "sqlite", "sync", "nostr", "nip46", "local-signing", "radrootsd", "geonames", "knowledge", "native", "full"] -required_radroots_dependencies = ["radroots-core", "radroots-identity", "radroots-protocol", "radroots-event", "radroots-event-codec", "radroots-trade", "radroots-signing", "radroots-transport", "radroots-storage"] -optional_radroots_dependencies = ["radroots-secrets", "radroots-storage-sqlite", "radroots-nostr", "radroots-nostr-connect", "radroots-transport-nostr", "radroots-sync", "radroots-geonames"] -modules = ["capability", "client", "diagnostics", "error", "farm", "listing", "signing", "storage", "sync", "trade", "transport"] +features = [ + "memory", + "sqlite", + "sync", + "nostr", + "nip46", + "local-signing", + "radrootsd", + "geonames", + "knowledge", + "native", + "full", +] +required_radroots_dependencies = [ + "radroots-core", + "radroots-identity", + "radroots-protocol", + "radroots-event", + "radroots-event-codec", + "radroots-trade", + "radroots-signing", + "radroots-transport", + "radroots-storage", +] +optional_radroots_dependencies = [ + "radroots-secrets", + "radroots-storage-sqlite", + "radroots-nostr", + "radroots-nostr-connect", + "radroots-transport-nostr", + "radroots-sync", + "radroots-geonames", +] +modules = [ + "capability", + "client", + "diagnostics", + "error", + "farm", + "listing", + "signing", + "storage", + "sync", + "trade", + "transport", +] root_exports = ["Client", "ClientBuilder", "Error", "Result"] forbidden = "Global runtimes or subscribers, hidden workers, process signals, CLI parsing, UI state, Studio databases, raw SQLx/upstream client types, broad wildcard reexports, or a nominal no_std claim." @@ -331,9 +617,37 @@ tier = "ordinary-user front door" platform = "std-only" responsibility = "Canonical Rust onboarding package with curated modules, safe defaults, stable convenience builders, domain aggregation, examples, and primary documentation." default_features = ["client"] -features = ["client", "native", "nostr", "nip46", "radrootsd", "geonames", "knowledge", "full"] -required_radroots_dependencies = ["radroots-sdk", "radroots-core", "radroots-identity", "radroots-event", "radroots-trade", "radroots-transport"] +features = [ + "client", + "native", + "nostr", + "nip46", + "radrootsd", + "geonames", + "knowledge", + "full", +] +required_radroots_dependencies = [ + "radroots-sdk", + "radroots-core", + "radroots-identity", + "radroots-event", + "radroots-trade", + "radroots-transport", +] optional_radroots_dependencies = [] -modules = ["client", "event", "farm", "identity", "knowledge", "listing", "signing", "storage", "sync", "trade", "transport"] +modules = [ + "client", + "event", + "farm", + "identity", + "knowledge", + "listing", + "signing", + "storage", + "sync", + "trade", + "transport", +] root_exports = ["Client", "ClientBuilder", "Error", "Result"] forbidden = "A public radroots::sdk namespace, wildcard reexport of radroots-sdk, duplicate engine implementation, CLI binary, hidden network/filesystem/keychain side effects, or exposure of every lower-crate symbol." diff --git a/flake.lock b/flake.lock @@ -80,11 +80,11 @@ ] }, "locked": { - "lastModified": 1784178955, - "narHash": "sha256-YtXHVFBzzqSidcEhPhfTcF2yzzu0p0yA7x07LOR+LaY=", + "lastModified": 1785131767, + "narHash": "sha256-VNbQv2P0zgaNh96mT4LrnX7hdXgiC5nBH+uvyrrVX7U=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "1785b85aeccca381caf8777133410f577b8f2f59", + "rev": "c67ce00525464a710971351c183ce67acb6ca827", "type": "github" }, "original": { diff --git a/tools/xtask/src/architecture.rs b/tools/xtask/src/architecture.rs @@ -1,5 +1,5 @@ use std::{ - collections::BTreeSet, + collections::{BTreeMap, BTreeSet}, fs, path::{Component, Path}, }; @@ -9,6 +9,9 @@ use serde::Deserialize; const DEVIATIONS_RELATIVE: &str = "docs/implementation/deviations.toml"; const ARCHITECTURE_RELATIVE: &str = "docs/specs/radroots_crates_release_v1.toml"; const ARCHITECTURE_ID: &str = "radroots.crates.release.v1"; +const PUBLIC_HOMEPAGE: &str = "https://radroots.org"; +const PUBLIC_README: &str = "README.md"; +const PUBLIC_AUTHORS: &[&str] = &["Tyson Lupul <tyson@radroots.org>"]; #[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] @@ -40,8 +43,25 @@ struct DeviationRecord { #[derive(Debug, Deserialize)] struct ArchitectureIdentity { spec_id: String, + initial_version: String, + edition: String, resolver: String, rust_version: String, + license: String, + canonical_repositories: Vec<String>, + repositories: BTreeMap<String, ArchitectureRepository>, + package: Vec<ArchitecturePackage>, +} + +#[derive(Debug, Deserialize)] +struct ArchitectureRepository { + url: String, + packages: Vec<String>, +} + +#[derive(Debug, Deserialize)] +struct ArchitecturePackage { + name: String, } #[derive(Debug, Deserialize)] @@ -50,16 +70,52 @@ struct WorkspaceManifest { } #[derive(Debug, Deserialize)] +struct WorkspaceMembershipManifest { + workspace: WorkspaceMembership, +} + +#[derive(Debug, Deserialize)] +struct WorkspaceMembership { + members: Vec<String>, +} + +#[derive(Debug, Deserialize)] struct WorkspaceMembers { members: Vec<String>, resolver: String, package: WorkspacePackage, + metadata: WorkspaceMetadata, +} + +#[derive(Debug, Deserialize)] +struct WorkspaceMetadata { + radroots: RadrootsWorkspaceMetadata, +} + +#[derive(Debug, Deserialize)] +struct RadrootsWorkspaceMetadata { + #[serde(rename = "public-package")] + public_package: PublicPackageMetadata, +} + +#[derive(Debug, Deserialize)] +struct PublicPackageMetadata { + version: String, + authors: Vec<String>, + readme: String, } #[derive(Debug, Deserialize)] struct WorkspacePackage { + version: String, + edition: String, #[serde(rename = "rust-version")] rust_version: String, + license: String, + repository: String, + homepage: String, + readme: String, + authors: Vec<String>, } pub fn validate(workspace_root: &Path) -> Result<(), String> { @@ -71,6 +127,7 @@ pub fn validate(workspace_root: &Path) -> Result<(), String> { .map_err(|error| format!("parse {}: {error}", architecture_path.display()))?; validate_workspace_toolchain(workspace_root, &architecture)?; + validate_public_package_metadata(workspace_root, &architecture)?; let ledger_path = workspace_root.join(DEVIATIONS_RELATIVE); let ledger_raw = fs::read_to_string(&ledger_path) @@ -101,6 +158,65 @@ fn validate_workspace_toolchain( manifest.workspace.package.rust_version, architecture.rust_version )); } + let workspace_package = &manifest.workspace.package; + let public_metadata = &manifest.workspace.metadata.radroots.public_package; + if public_metadata.version != architecture.initial_version + || architecture.initial_version != "0.1.0" + { + return Err(format!( + "public package version source {} must match architecture initial_version {}", + public_metadata.version, architecture.initial_version + )); + } + if public_metadata.authors != PUBLIC_AUTHORS { + return Err("public package authors source must match the workspace convention".to_owned()); + } + if public_metadata.readme != PUBLIC_README { + return Err(format!( + "public package readme source must be {PUBLIC_README}" + )); + } + if workspace_package.edition != architecture.edition || architecture.edition != "2024" { + return Err(format!( + "workspace edition {} must match architecture edition {}", + workspace_package.edition, architecture.edition + )); + } + if workspace_package.license != architecture.license { + return Err(format!( + "workspace license {} must match architecture license {}", + workspace_package.license, architecture.license + )); + } + if !architecture + .canonical_repositories + .contains(&workspace_package.repository) + { + return Err(format!( + "workspace repository {} is not canonical", + workspace_package.repository + )); + } + if workspace_package.homepage != PUBLIC_HOMEPAGE { + return Err(format!( + "workspace homepage {} must be {PUBLIC_HOMEPAGE}", + workspace_package.homepage + )); + } + if workspace_package.authors != PUBLIC_AUTHORS { + return Err("workspace authors must match the public package convention".to_owned()); + } + if !workspace_root.join(&workspace_package.readme).is_file() { + return Err(format!( + "workspace readme {} does not exist", + workspace_package.readme + )); + } + for license in ["LICENSE-MIT", "LICENSE-APACHE"] { + if !workspace_root.join(license).is_file() { + return Err(format!("workspace is missing {license}")); + } + } let toolchain_path = workspace_root.join("rust-toolchain.toml"); let toolchain_raw = fs::read_to_string(&toolchain_path) .map_err(|error| format!("read {}: {error}", toolchain_path.display()))?; @@ -120,11 +236,168 @@ fn validate_workspace_toolchain( Ok(()) } +fn validate_public_package_metadata( + workspace_root: &Path, + architecture: &ArchitectureIdentity, +) -> Result<(), String> { + let workspace_raw = fs::read_to_string(workspace_root.join("Cargo.toml")) + .map_err(|error| format!("read workspace Cargo.toml: {error}"))?; + let workspace = toml::from_str::<WorkspaceManifest>(&workspace_raw) + .map_err(|error| format!("parse workspace Cargo.toml: {error}"))?; + let repository = architecture + .repositories + .values() + .find(|repository| repository.url == workspace.workspace.package.repository) + .ok_or_else(|| "workspace repository has no architecture allocation".to_owned())?; + let local_packages = repository.packages.iter().collect::<BTreeSet<_>>(); + let all_packages = architecture + .package + .iter() + .map(|package| package.name.as_str()) + .collect::<BTreeSet<_>>(); + + for member in &workspace.workspace.members { + let manifest_path = workspace_root.join(member).join("Cargo.toml"); + let raw = fs::read_to_string(&manifest_path) + .map_err(|error| format!("read {}: {error}", manifest_path.display()))?; + let manifest = raw + .parse::<toml::Value>() + .map_err(|error| format!("parse {}: {error}", manifest_path.display()))?; + let package = manifest + .get("package") + .and_then(toml::Value::as_table) + .ok_or_else(|| format!("{} is missing [package]", manifest_path.display()))?; + let name = package + .get("name") + .and_then(toml::Value::as_str) + .ok_or_else(|| format!("{} is missing package.name", manifest_path.display()))?; + if !all_packages.contains(name) { + continue; + } + if !local_packages.contains(&name.to_owned()) { + return Err(format!( + "public package {name} belongs to a different canonical repository" + )); + } + validate_public_manifest_field( + package, + "version", + &workspace.workspace.package.version, + &architecture.initial_version, + name, + )?; + validate_public_manifest_field( + package, + "edition", + &workspace.workspace.package.edition, + &architecture.edition, + name, + )?; + validate_public_manifest_field( + package, + "rust-version", + &workspace.workspace.package.rust_version, + &architecture.rust_version, + name, + )?; + validate_public_manifest_field( + package, + "license", + &workspace.workspace.package.license, + &architecture.license, + name, + )?; + validate_public_manifest_field( + package, + "repository", + &workspace.workspace.package.repository, + &repository.url, + name, + )?; + validate_public_manifest_field( + package, + "homepage", + &workspace.workspace.package.homepage, + PUBLIC_HOMEPAGE, + name, + )?; + let authors = resolve_public_authors(package, &workspace.workspace.package.authors) + .ok_or_else(|| format!("public package {name} must declare authors"))?; + if authors != PUBLIC_AUTHORS { + return Err(format!( + "public package {name} authors must match the workspace convention" + )); + } + let readme = package.get("readme").and_then(toml::Value::as_str); + if readme != Some(PUBLIC_README) + || !workspace_root.join(member).join(PUBLIC_README).is_file() + { + return Err(format!( + "public package {name} must use an existing crate-local {PUBLIC_README}" + )); + } + if package.get("publish").and_then(toml::Value::as_bool) != Some(false) { + return Err(format!( + "public package {name} must remain publish = false during migration" + )); + } + } + Ok(()) +} + +fn validate_public_manifest_field( + package: &toml::value::Table, + key: &str, + workspace_value: &str, + expected: &str, + package_name: &str, +) -> Result<(), String> { + let value = resolve_public_string(package, key, workspace_value) + .ok_or_else(|| format!("public package {package_name} must declare {key}"))?; + if value != expected { + return Err(format!( + "public package {package_name} {key} {value} must be {expected}" + )); + } + Ok(()) +} + +fn resolve_public_string<'a>( + package: &'a toml::value::Table, + key: &str, + workspace_value: &'a str, +) -> Option<&'a str> { + match package.get(key)? { + toml::Value::String(value) => Some(value), + toml::Value::Table(value) + if value.get("workspace").and_then(toml::Value::as_bool) == Some(true) => + { + Some(workspace_value) + } + _ => None, + } +} + +fn resolve_public_authors<'a>( + package: &'a toml::value::Table, + workspace_authors: &'a [String], +) -> Option<Vec<&'a str>> { + match package.get("authors")? { + toml::Value::Array(values) => values.iter().map(toml::Value::as_str).collect(), + toml::Value::Table(value) + if value.get("workspace").and_then(toml::Value::as_bool) == Some(true) => + { + Some(workspace_authors.iter().map(String::as_str).collect()) + } + _ => None, + } +} + fn validate_workspace_members(workspace_root: &Path) -> Result<(), String> { let manifest_path = workspace_root.join("Cargo.toml"); let manifest_raw = fs::read_to_string(&manifest_path) .map_err(|error| format!("read {}: {error}", manifest_path.display()))?; - let manifest = toml::from_str::<WorkspaceManifest>(&manifest_raw) + let manifest = toml::from_str::<WorkspaceMembershipManifest>(&manifest_raw) .map_err(|error| format!("parse {}: {error}", manifest_path.display()))?; let declared = manifest .workspace @@ -316,14 +589,15 @@ fn is_iso_date(value: &str) -> bool { #[cfg(test)] mod tests { use std::{ + collections::BTreeMap, fs, path::PathBuf, time::{SystemTime, UNIX_EPOCH}, }; use super::{ - ArchitectureIdentity, validate_ledger, validate_workspace_members, - validate_workspace_toolchain, + ArchitectureIdentity, ArchitecturePackage, ArchitectureRepository, validate_ledger, + validate_public_package_metadata, validate_workspace_members, validate_workspace_toolchain, }; fn test_root(label: &str) -> PathBuf { @@ -361,6 +635,34 @@ adr_required = false "# } + fn architecture() -> ArchitectureIdentity { + ArchitectureIdentity { + spec_id: "radroots.crates.release.v1".to_string(), + initial_version: "0.1.0".to_string(), + edition: "2024".to_string(), + resolver: "3".to_string(), + rust_version: "1.97.1".to_string(), + license: "MIT OR Apache-2.0".to_string(), + canonical_repositories: vec!["https://github.com/radrootslabs/sdk".to_string()], + repositories: BTreeMap::from([( + "sdk".to_string(), + ArchitectureRepository { + url: "https://github.com/radrootslabs/sdk".to_string(), + packages: vec!["radroots".to_string()], + }, + )]), + package: vec![ArchitecturePackage { + name: "radroots".to_string(), + }], + } + } + + fn complete_workspace_manifest(members: &str) -> String { + format!( + "[workspace]\nmembers = [{members}]\nresolver = \"3\"\n\n[workspace.package]\nversion = \"0.1.0\"\nedition = \"2024\"\nrust-version = \"1.97.1\"\nlicense = \"MIT OR Apache-2.0\"\nrepository = \"https://github.com/radrootslabs/sdk\"\nhomepage = \"https://radroots.org\"\nreadme = \"README\"\nauthors = [\"Tyson Lupul <tyson@radroots.org>\"]\n\n[workspace.metadata.radroots.public-package]\nversion = \"0.1.0\"\nauthors = [\"Tyson Lupul <tyson@radroots.org>\"]\nreadme = \"README.md\"\n" + ) + } + #[test] fn accepts_complete_active_deviation() { let root = test_root("complete"); @@ -413,21 +715,17 @@ adr_required = false #[test] fn workspace_toolchain_requires_exact_resolver_and_rust_version() { let root = test_root("workspace_toolchain"); - fs::write( - root.join("Cargo.toml"), - "[workspace]\nmembers = []\nresolver = \"3\"\n\n[workspace.package]\nrust-version = \"1.97.1\"\n", - ) - .expect("write workspace manifest"); + fs::write(root.join("Cargo.toml"), complete_workspace_manifest("")) + .expect("write workspace manifest"); + for path in ["README", "LICENSE-MIT", "LICENSE-APACHE"] { + fs::write(root.join(path), "fixture\n").expect("write workspace metadata file"); + } fs::write( root.join("rust-toolchain.toml"), "[toolchain]\nchannel = \"1.97.1\"\n", ) .expect("write toolchain"); - let architecture = ArchitectureIdentity { - spec_id: "radroots.crates.release.v1".to_string(), - resolver: "3".to_string(), - rust_version: "1.97.1".to_string(), - }; + let architecture = architecture(); validate_workspace_toolchain(&root, &architecture).expect("exact toolchain policy"); fs::write( @@ -440,4 +738,31 @@ adr_required = false assert!(error.contains("channel must match")); let _ = fs::remove_dir_all(root); } + + #[test] + fn public_package_metadata_requires_canonical_inheritance() { + let root = test_root("public_package_metadata"); + fs::create_dir_all(root.join("crates/radroots")).expect("create public package"); + fs::write( + root.join("Cargo.toml"), + complete_workspace_manifest("\"crates/radroots\""), + ) + .expect("write workspace manifest"); + let manifest = "[package]\nname = \"radroots\"\nversion.workspace = true\nedition.workspace = true\nrust-version.workspace = true\nlicense.workspace = true\nrepository.workspace = true\nhomepage.workspace = true\nauthors.workspace = true\nreadme = \"README.md\"\npublish = false\n"; + fs::write(root.join("crates/radroots/Cargo.toml"), manifest) + .expect("write public manifest"); + fs::write(root.join("crates/radroots/README.md"), "fixture\n") + .expect("write public readme"); + validate_public_package_metadata(&root, &architecture()).expect("canonical metadata"); + + fs::write( + root.join("crates/radroots/Cargo.toml"), + manifest.replace("authors.workspace = true\n", ""), + ) + .expect("write incomplete public manifest"); + let error = validate_public_package_metadata(&root, &architecture()) + .expect_err("missing authors must fail"); + assert!(error.contains("must declare authors")); + let _ = fs::remove_dir_all(root); + } } diff --git a/tools/xtask/src/contract/nip09_reconciliation.rs b/tools/xtask/src/contract/nip09_reconciliation.rs @@ -14328,7 +14328,7 @@ fn validate_governed_compiler_inputs(workspace_root: &Path) -> Result<(), String let expected_toolchain: toml::Value = toml::from_str( r#" [toolchain] -channel = "1.97.0" +channel = "1.97.1" components = ["clippy", "rust-analyzer", "rust-src", "rustfmt"] targets = ["wasm32-unknown-unknown"] "#, @@ -14336,7 +14336,7 @@ targets = ["wasm32-unknown-unknown"] .map_err(|error| format!("parse governed Rust toolchain expectation: {error}"))?; if toolchain != expected_toolchain { return Err(format!( - "{RUST_TOOLCHAIN_RELATIVE} must remain the exact governed Rust 1.97.0 toolchain document" + "{RUST_TOOLCHAIN_RELATIVE} must remain the exact governed Rust 1.97.1 toolchain document" )); } for legacy_relative in ["rust-toolchain", ".cargo/config"] { @@ -14537,7 +14537,7 @@ xtask = "run -q -p xtask --" "{WORKSPACE_CARGO_MANIFEST_RELATIVE} must not exclude or narrow the default governed workspace member graph" )); } - if workspace.get("resolver").and_then(toml::Value::as_str) != Some("2") + if workspace.get("resolver").and_then(toml::Value::as_str) != Some("3") || workspace_package .get("edition") .and_then(toml::Value::as_str) @@ -14545,10 +14545,10 @@ xtask = "run -q -p xtask --" || workspace_package .get("rust-version") .and_then(toml::Value::as_str) - != Some("1.97.0") + != Some("1.97.1") { return Err(format!( - "{WORKSPACE_CARGO_MANIFEST_RELATIVE} must retain resolver 2, edition 2024, and rust-version 1.97.0 compiler authority" + "{WORKSPACE_CARGO_MANIFEST_RELATIVE} must retain resolver 3, edition 2024, and rust-version 1.97.1 compiler authority" )); } if workspace_manifest.get("replace").is_some() @@ -21092,12 +21092,12 @@ async fn nip09_reconciliation_v1_result_vector() { let toolchain = fs::read_to_string(&toolchain_path).expect("Rust toolchain"); fs::write( &toolchain_path, - toolchain.replacen("channel = \"1.97.0\"", "channel = \"nightly\"", 1), + toolchain.replacen("channel = \"1.97.1\"", "channel = \"nightly\"", 1), ) .expect("write toolchain mutation"); let error = validate_governed_compiler_inputs(workspace.path()) .expect_err("Rust toolchain mutation must fail"); - assert!(error.contains("exact governed Rust 1.97.0"), "{error}"); + assert!(error.contains("exact governed Rust 1.97.1"), "{error}"); fs::write(&toolchain_path, toolchain).expect("restore Rust toolchain"); let legacy_toolchain_path = workspace.path().join("rust-toolchain"); @@ -21224,7 +21224,7 @@ async fn nip09_reconciliation_v1_result_vector() { for (label, mutation) in [ ( "resolver", - workspace_manifest.replacen("resolver = \"2\"", "resolver = \"1\"", 1), + workspace_manifest.replacen("resolver = \"3\"", "resolver = \"1\"", 1), ), ( "edition", @@ -21237,7 +21237,7 @@ async fn nip09_reconciliation_v1_result_vector() { let error = validate_governed_compiler_inputs(workspace.path()) .expect_err("workspace compiler authority mutation must fail"); assert!( - error.contains("resolver 2, edition 2024, and rust-version 1.97.0"), + error.contains("resolver 3, edition 2024, and rust-version 1.97.1"), "{label} produced unexpected error: {error}" ); fs::write(&workspace_manifest_path, &workspace_manifest)