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:
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)