commit 9600081e87d5f8de95260f683039a889bd50aa0e
parent 3f51d10bd8b9e1fb03ef76f540b530327de2869e
Author: triesap <tyson@radroots.org>
Date: Fri, 31 Jul 2026 16:28:33 +0000
nostr: quarantine superseded package surface
- expose only the chartered protocol adapter modules and feature vocabulary
- migrate in-capsule consumers to canonical event signing and conversion APIs
- retire prefixed compatibility names while recording out-of-scope consumers
- bind the reviewed public API and event contracts to the quarantined surface
Diffstat:
55 files changed, 1261 insertions(+), 1381 deletions(-)
diff --git a/contracts/event_boundary_matrix.md b/contracts/event_boundary_matrix.md
@@ -102,8 +102,8 @@ event id wins at equal time. Side-specific errors identify an invalid previous
or current candidate before revision comparison.
The `radroots_nostr` `events` feature seals strict FoodAvailability wire parts
-behind a builder whose timestamp cannot be mutated after validation. It supports
-local signing and typed client publication; generic authoring rejects focused
+behind a builder whose timestamp cannot be mutated after validation. With the
+`signing` feature it supports local signing; generic authoring rejects focused
and mixed kind-`30402` profiles. Signed-event relay remains transport-only.
The non-default `legacy-ingest` replica feature verifies kind-`30402` NIP-01
events first, selects the raw addressable head before profile decoding, and
@@ -205,8 +205,9 @@ relay availability.
The event-contract registry v7 classifies `radroots.social.comment.v1` as
`TypedOnly` for authoring and `AdmissionOnly` for matching. Registry versions
-`1` through `6` are stale. Generic kind-`1111` signing and client publication
-fail before signer access. The complete operation surface is exactly
+`1` through `6` are stale. Generic kind-`1111` signing fails before signer
+access; publication remains transport-owned. The complete operation surface
+is exactly
`social.comment.build_authored_draft`,
`social.comment.project_verified_event`, and
`social.comment.verify_and_admit_event`.
@@ -252,8 +253,8 @@ qualifying inputs.
The event-contract registry v7 classifies
`radroots.social.deletion_request.v1` as `TypedOnly` for authoring and
-`AdmissionOnly` for matching. Generic kind-`5` signing and client publication
-fail before signer access.
+`AdmissionOnly` for matching. Generic kind-`5` signing fails before signer
+access; publication remains transport-owned.
The complete operation surface is exactly
`social.deletion_request.build_authored_draft`,
@@ -275,9 +276,9 @@ not weaken or add effect fields to the request corpus.
| profile | 0 | AuthoredProfile / RadrootsInboundProfileMetadata | events.profile.publish, events.profile.list, events.profile.get | publish must use `profile.build_authored_draft`; inbound projection must use `profile.parse_inbound_metadata`; authored output is deterministic JSON with no marker tag |
| follow | 3 | Follow | events.follow.publish, events.follow.list, events.follow.get | replaceable event |
| post | 1 | AuthoredUpdate / AuthoredPhotoUpdate / AuthoredAsk / RadrootsInboundPostProjection | events.post.publish, events.post.list, events.post.get | ordinary kind-1 reads remain generic; exact root-card subtypes require verified admission; any `e` tag produces a thread-excluded candidate without a Reply claim |
-| reply | 1 | AuthoredNip10Reply / RadrootsInboundNip10ReplyProjection / RadrootsAdmittedNip10ReplyEvent / RadrootsNostrNip10ReplyEventBuilder | social.reply.build_authored_draft, social.reply.project_verified_event, social.reply.verify_and_admit_event | strict marked direct/nested NIP-10 authoring; verified marked or positional inbound admission with advisory-metadata diagnostics; never a root card; target existence, kind, author, and relay availability are not proven |
-| comment | 1111 | AuthoredNip22Comment / RadrootsInboundNip22CommentProjection / RadrootsAdmittedNip22CommentEvent / RadrootsNostrNip22CommentEventBuilder | social.comment.build_authored_draft, social.comment.project_verified_event, social.comment.verify_and_admit_event | strict NIP-22 event/address roots limited to kinds `30402`, `31922`, and `31923`; tolerant verified projection; registry-v7 typed-only authoring and admission-only matching |
-| deletion_request | 5 | AuthoredNip09DeletionRequest / RadrootsInboundNip09DeletionProjection / RadrootsAdmittedNip09DeletionRequestEvent / RadrootsNip09SuppressionDecision / RadrootsNostrNip09DeletionRequestEventBuilder | social.deletion_request.build_authored_draft, social.deletion_request.project_verified_event, social.deletion_request.verify_and_admit_event, social.deletion_request.evaluate_suppression | effect-free NIP-09 request authoring and verified projection plus pure immutable suppression evaluation; same-author direct event targets and inclusive address cutoffs; kind-5 immunity; advisory kinds ignored; registry-v7 typed-only authoring and admission-only matching |
+| reply | 1 | AuthoredNip10Reply / RadrootsInboundNip10ReplyProjection / RadrootsAdmittedNip10ReplyEvent / Nip10ReplyBuilder | social.reply.build_authored_draft, social.reply.project_verified_event, social.reply.verify_and_admit_event | strict marked direct/nested NIP-10 authoring; verified marked or positional inbound admission with advisory-metadata diagnostics; never a root card; target existence, kind, author, and relay availability are not proven |
+| comment | 1111 | AuthoredNip22Comment / RadrootsInboundNip22CommentProjection / RadrootsAdmittedNip22CommentEvent / Nip22CommentBuilder | social.comment.build_authored_draft, social.comment.project_verified_event, social.comment.verify_and_admit_event | strict NIP-22 event/address roots limited to kinds `30402`, `31922`, and `31923`; tolerant verified projection; registry-v7 typed-only authoring and admission-only matching |
+| deletion_request | 5 | AuthoredNip09DeletionRequest / RadrootsInboundNip09DeletionProjection / RadrootsAdmittedNip09DeletionRequestEvent / RadrootsNip09SuppressionDecision / Nip09DeletionRequestBuilder | social.deletion_request.build_authored_draft, social.deletion_request.project_verified_event, social.deletion_request.verify_and_admit_event, social.deletion_request.evaluate_suppression | effect-free NIP-09 request authoring and verified projection plus pure immutable suppression evaluation; same-author direct event targets and inclusive address cutoffs; kind-5 immunity; advisory kinds ignored; registry-v7 typed-only authoring and admission-only matching |
| reaction | 7 | Reaction | events.reaction.publish, events.reaction.list, events.reaction.get | requires event, pubkey, or address tags |
| repost | 6 | Repost | events.repost.publish, events.repost.list, events.repost.get | NIP-18 kind-1 repost surface |
| generic_repost | 16 | GenericRepost | events.generic_repost.publish, events.generic_repost.list, events.generic_repost.get | NIP-18 generic repost surface |
@@ -304,7 +305,7 @@ not weaken or add effect fields to the request corpus.
| document | 30361 | Document | events.document.publish, events.document.list, events.document.get | requires `d` and pubkey tags; optional address tag |
| resource_area | 30370 | ResourceArea | events.resource_area.publish, events.resource_area.list, events.resource_area.get | addressable; GCS location and `g` tag required |
| resource_cap | 30371 | ResourceHarvestCap | events.resource_cap.publish, events.resource_cap.list, events.resource_cap.get | addressable; required address, pubkey, key, start, and end tags |
-| food_availability | 30402 | FoodAvailabilityDetails / RadrootsInboundFoodAvailabilityProjection / RadrootsAdmittedFoodAvailabilityEvent / RadrootsNostrFoodAvailabilityEventBuilder | food_availability.build_authored_draft, food_availability.project_verified_event, food_availability.verify_and_admit_event, food_availability.validate_revision | focused `radroots.food.availability.v1` profile; strict deterministic authoring, verified projection/admission, stable-coordinate revision validation, sealed Nostr signing/publication, generic-authoring reservation, and raw-head-first partitioning only behind the non-default `legacy-ingest` replica feature; BUD-02 upload evidence remains a runtime prerequisite |
+| food_availability | 30402 | FoodAvailabilityDetails / RadrootsInboundFoodAvailabilityProjection / RadrootsAdmittedFoodAvailabilityEvent / FoodAvailabilityBuilder | food_availability.build_authored_draft, food_availability.project_verified_event, food_availability.verify_and_admit_event, food_availability.validate_revision | focused `radroots.food.availability.v1` profile; strict deterministic authoring, verified projection/admission, stable-coordinate revision validation, sealed Nostr signing, transport-owned publication, generic-authoring reservation, and raw-head-first partitioning only behind the non-default `legacy-ingest` replica feature; BUD-02 upload evidence remains a runtime prerequisite |
| operational_listing | 30402 | OperationalListing | events.operational_listing.publish, events.operational_listing.list, events.operational_listing.get | NIP-99 classified-listing kind with the richer Radroots operational profile; canonical Markdown content and tags; farm author required |
| dvm_request | 5000-5999 | JobRequest | events.dvm_request.publish, events.dvm_request.list, events.dvm_request.get | generic DVM request surface |
| dvm_result | 6000-6999 | JobResult | events.dvm_result.publish, events.dvm_result.list, events.dvm_result.get | generic DVM result surface |
diff --git a/contracts/events/social-events.md b/contracts/events/social-events.md
@@ -181,12 +181,12 @@ and are accepted only after deserialization revalidates the registry version,
contract, kind, shape, policy, recomputed event id, and known fields. The
frozen-draft signing boundary repeats that validation, so stale version-`1`
through version-`6` drafts must be rebuilt. Typed root posts, Replies,
-Comments, and Deletion Requests enter Nostr signing and client publication
-only through opaque typed builders that expose timestamp selection and
-signing, but no raw tag/content mutation or public conversion to the upstream
-builder. The opaque generic builder rejects kind `0`, every kind `1` event,
-kind `5`, and kind `1111` at both direct signing and client publication before
-a signer is consulted.
+Comments, and Deletion Requests enter Nostr signing only through opaque typed
+builders that expose timestamp selection and signing, but no raw tag/content
+mutation or public conversion to the upstream builder. Publication remains a
+transport concern operating on signed events. The opaque generic builder
+rejects kind `0`, every kind `1` event, kind `5`, and kind `1111` before a
+signer is consulted.
### NIP-10 Reply Trust Layers
@@ -217,8 +217,8 @@ Strict authoring is deterministic. A direct Reply emits
two-element `p` tag. A nested Reply emits the root `e` tag, then
`["e",<parent-id>,<relay-or-empty>,"reply"]`, then the root and parent author
`p` tags in that order; equal authors are emitted once. No other authored tag
-shape is accepted. Signing and client publication are exposed only through the
-sealed `RadrootsNostrNip10ReplyEventBuilder`.
+shape is accepted. Signing is exposed only through the sealed
+`Nip10ReplyBuilder`; publication remains transport-owned.
Inbound projection requires a signature-and-id verified envelope. It accepts
preferred marked `e` references, including the optional NIP-10 author hint, and
@@ -688,13 +688,13 @@ enter this comparison. Kind, author, `d`, and `published_at` must remain stable.
have a later `created_at`, or the lower event id when both timestamps are equal. Invalid previous
and current inputs have side-specific errors.
-With the `events` feature, `radroots_nostr_build_food_availability_event` fixes `created_at` during
+With the `events` feature, `build_food_availability_event` fixes `created_at` during
typed construction, derives the exact strict wire parts, and returns a sealed builder with no raw
-tag, content, or timestamp mutation. The builder supports local signing and, with the `client`
-feature, typed relay publication. Generic builder signing and client publication reject focused and
-mixed-marker kind-`30402` events before signer access. Marker-free generic NIP-99 and
-operational-only builders remain available for explicit compatibility, while relaying an already
-signed event remains transport-only and establishes no Radroots authoring claim.
+tag, content, or timestamp mutation. With the `signing` feature, the builder supports local signing.
+Generic builder signing rejects focused and mixed-marker kind-`30402` events before signer access.
+Marker-free generic NIP-99 and operational-only builders remain available for explicit
+compatibility. Relay publication remains transport-only and establishes no Radroots authoring
+claim.
Behind the explicit non-default `legacy-ingest` feature, legacy replica ingestion verifies
kind-`30402` identifiers and signatures before acquiring its write transaction, then selects the
diff --git a/crates/event_store/contracts/source_maintenance_v1.manifest.json b/crates/event_store/contracts/source_maintenance_v1.manifest.json
@@ -873,8 +873,8 @@
{
"role": "contract_command_authority",
"path": "tools/xtask/src/contract.rs",
- "byte_length": 508374,
- "sha256": "c498f6fda5e595c7165465a9f261b45acc7ef47762e1fc04fd94026f9ecf2167",
+ "byte_length": 508073,
+ "sha256": "26d1825a0d7a4a3bb983478f2ef87dc228cbfb68f794bb52864e34a62ef1eead",
"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 @@
-032aab678a257acd2215d631b53d4883b41c74d023725d3ccd0518d8d5858a86
+ef7894006bc64f8b72718708f16babe3302209c6b1e74465def57d6b1862a9b6
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\": \"96ea98a5abf3348b61565954cd34f2c622411d8dd34205ef04134bbe0e3d3f2b\",\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\": \"02dfe1b450fbdac16e718888215b4dd5c85d8975440fa21e8f439fb24c2b2990\",\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\": \"ab2724188f8d08c897eebea2533a635e7c74282a25e84e4c0c37e78b08837a43\",\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\": \"074f85b663444ac150239ecd8441ea4a96ad83a798a55e22d2e5e2f7ee943a8c\",\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\": \"02dfe1b450fbdac16e718888215b4dd5c85d8975440fa21e8f439fb24c2b2990\",\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\": 12440,\n \"sha256\": \"8981f78d3ea85454a8cf7be156b3eef5659b399f1631d7c1068e7c336988070d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_currency_value_authority\",\n \"path\": \"crates/core/src/currency.rs\",\n \"byte_length\": 4142,\n \"sha256\": \"42e6da2d8d2fdd6955dc2d83e98dd00266e02bc910b69923b117662c05089d14\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_decimal_value_authority\",\n \"path\": \"crates/core/src/decimal.rs\",\n \"byte_length\": 7839,\n \"sha256\": \"4b1d681a92d7a9e074bee7e1f20eb1499bb05bfc6528a6c9ba69fa7d00416550\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_money_value_authority\",\n \"path\": \"crates/core/src/money.rs\",\n \"byte_length\": 8025,\n \"sha256\": \"3f30bc21e21951a62fdc5d4033736ed42a883df590e8403940775bd2edfeebc5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_percent_value_authority\",\n \"path\": \"crates/core/src/percent.rs\",\n \"byte_length\": 2652,\n \"sha256\": \"42ceab109881329f3539d06a0ee0381ab4359985fe185a18d58a9c9558c5eb7f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_quantity_value_authority\",\n \"path\": \"crates/core/src/quantity.rs\",\n \"byte_length\": 6785,\n \"sha256\": \"d14e619da3829cdaf3ca7385fb892d330c286c1e21455c135c37518cbb588b5f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_quantity_price_value_authority\",\n \"path\": \"crates/core/src/quantity_price.rs\",\n \"byte_length\": 7061,\n \"sha256\": \"d60f70377099470ed283f45868a5119d7bb46143cb250b5082a4c038ba7f6cdc\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_unit_value_authority\",\n \"path\": \"crates/core/src/unit.rs\",\n \"byte_length\": 10023,\n \"sha256\": \"550e9582b6a5290aac3f637b83853b21fefcbab92c432d067c83448f4b2fe3e9\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_public_surface\",\n \"path\": \"crates/blossom/src/lib.rs\",\n \"byte_length\": 510,\n \"sha256\": \"a4dfcbd193457c50c1b0fbfc91bb547981ecd3a6e23cfc6f1030edfb511dc58c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_authorization_authority\",\n \"path\": \"crates/blossom/src/authorization.rs\",\n \"byte_length\": 39360,\n \"sha256\": \"461947b30516315a342b3b5697599f701d27050888f29f67f5d7a7ad4afa4c28\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_descriptor_authority\",\n \"path\": \"crates/blossom/src/descriptor.rs\",\n \"byte_length\": 13702,\n \"sha256\": \"b2a4ffa760256e1316f70e012d200e2b5f4afd8ede771b85a5147f96b247f599\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_error_authority\",\n \"path\": \"crates/blossom/src/error.rs\",\n \"byte_length\": 17229,\n \"sha256\": \"02af55beacf437040be17d1fc3271d6e2a62915f656ec2dbe06247deef83f95a\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_hash_authority\",\n \"path\": \"crates/blossom/src/hash.rs\",\n \"byte_length\": 11006,\n \"sha256\": \"45eca0d81ac0f46c305a32f81aafcdd90b14679d0614f72862289a6e5d4cb08f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_media_type_authority\",\n \"path\": \"crates/blossom/src/media_type.rs\",\n \"byte_length\": 2368,\n \"sha256\": \"69db5c0f9fcdd7dbe1f22daa499f65603ae4ce198083dab2c73a36813fa18a46\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_url_authority\",\n \"path\": \"crates/blossom/src/url.rs\",\n \"byte_length\": 14580,\n \"sha256\": \"342c995fcf620e5fb32461a7d8276f5668ba2662890bd32d12780cc9121c6451\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_public_surface\",\n \"path\": \"crates/event/src/lib.rs\",\n \"byte_length\": 1892,\n \"sha256\": \"5d609b963a9b8db18ef96a10f394617413734d2631774d3296e6d8fc029cb02c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_contract_facade\",\n \"path\": \"crates/event/src/contract.rs\",\n \"byte_length\": 208,\n \"sha256\": \"27466bf36461071931f391c60646a13f7781d19584583166cc54c0eece76d010\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_contract_registry_v7_authority\",\n \"path\": \"crates/event/src/contract/registry_v7.rs\",\n \"byte_length\": 145805,\n \"sha256\": \"0a62603f6fc05dc9f758561cf7da258c676ada810ceaeca7fb151364a5c83d62\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_envelope_authority\",\n \"path\": \"crates/event/src/envelope.rs\",\n \"byte_length\": 29310,\n \"sha256\": \"29f8d8c4b17c01cb5a8c7f59e4ce52e134180e0e6f37d265063d278b8f2ff26e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_verification_typestate_authority\",\n \"path\": \"crates/event/src/verification.rs\",\n \"byte_length\": 9400,\n \"sha256\": \"417acb2ce670d266b1fa4fcafd6b48a910218deab38f57fb8b942056db76f94d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_admission_typestate_authority\",\n \"path\": \"crates/event/src/admission.rs\",\n \"byte_length\": 7052,\n \"sha256\": \"62bd2ceb0f434946fdfc2b81f4efb13738676a29a6936c23a427e43aadf2d9cb\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_head_facade\",\n \"path\": \"crates/event/src/event_head.rs\",\n \"byte_length\": 97,\n \"sha256\": \"f761ff3e74c4f5e1e28381db00ce698c633ff048669b22984d14a587482e8e83\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_head_v1_authority\",\n \"path\": \"crates/event/src/event_head/v1.rs\",\n \"byte_length\": 6849,\n \"sha256\": \"9f4144d8d240023cf493ce0b538ade4c16dc44204d6b5f2797152caf6f9e7dba\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_ids_authority\",\n \"path\": \"crates/event/src/id.rs\",\n \"byte_length\": 48381,\n \"sha256\": \"a08fe3873815453a03318a706e2fa98a8a6728ec69d24368a87ec60025566fe0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_trade_authority\",\n \"path\": \"crates/event/src/trade.rs\",\n \"byte_length\": 65549,\n \"sha256\": \"f818a7287ed82de3fb9ef1d973f0fb18d84b30eb4827ddc576ee502dd980145f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_kinds_authority\",\n \"path\": \"crates/event/src/kinds.rs\",\n \"byte_length\": 34961,\n \"sha256\": \"8b3ce6193cab1f7e1587d0c1b2880a81b0aa43c77d89671b602772db37edcebf\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_tags_authority\",\n \"path\": \"crates/event/src/tags.rs\",\n \"byte_length\": 4530,\n \"sha256\": \"cb8f12a639fc72d9238e32495d9e67e928e6627fb8c94ec0a58c5d95e7373cd6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_draft_authority\",\n \"path\": \"crates/event/src/draft.rs\",\n \"byte_length\": 51150,\n \"sha256\": \"ecc619aae28d688d13f35467398f17766b60f26c2bf3616d772ce65b7fa4fb53\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_calendar_authority\",\n \"path\": \"crates/event/src/calendar.rs\",\n \"byte_length\": 97992,\n \"sha256\": \"73e79d61ee175cb46e6123e1d28239252ddf0ad094dc1113bdb1286b63b88d57\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_classified_listing_authority\",\n \"path\": \"crates/event/src/classified_listing.rs\",\n \"byte_length\": 7956,\n \"sha256\": \"ac58484b87c7712c81f50f884d1c0dd60938571aa5f6f05d555191f529a4c2b0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_profile_authority\",\n \"path\": \"crates/event/src/profile.rs\",\n \"byte_length\": 17011,\n \"sha256\": \"572bfe3b6f1711d109db445077f0a8453cad3f021cc0638f79201b618e16b978\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_post_authority\",\n \"path\": \"crates/event/src/post.rs\",\n \"byte_length\": 19968,\n \"sha256\": \"a822cd51eff9cbaa39db998cc5c90d117f7a983f0fe2d42d42118cb00e95982c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_comment_authority\",\n \"path\": \"crates/event/src/comment.rs\",\n \"byte_length\": 34745,\n \"sha256\": \"24b7fda13229f21cee5cef2a9941e3aaafdbc486b19ed42731b0b6ee37c28703\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_food_availability_authority\",\n \"path\": \"crates/event/src/food_availability.rs\",\n \"byte_length\": 42829,\n \"sha256\": \"52472c07eb0855d884c60755dc3a3e1a963793451d707e51f769f2d78384f318\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_deletion_authority\",\n \"path\": \"crates/event/src/deletion.rs\",\n \"byte_length\": 30022,\n \"sha256\": \"8c3f2e32407520a8e8242c1293af32613c648fb76218b8003a18929ac0b3811f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_dto_authority\",\n \"path\": \"crates/event/src/dto.rs\",\n \"byte_length\": 5038,\n \"sha256\": \"9e228c95ff6ff33f99441d8682781fd0a1c4d3f1db24284a43985dcbac3ba136\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_farm_crdt_authority\",\n \"path\": \"crates/event/src/farm_crdt.rs\",\n \"byte_length\": 21118,\n \"sha256\": \"cec265ac9c42b59a14be4eb96924d26a83477c27291f667f23e6e47a64b6b2c7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_knowledge_authority\",\n \"path\": \"crates/event/src/knowledge.rs\",\n \"byte_length\": 54624,\n \"sha256\": \"3d55ff88a4e30d5d605f9ae4b2e96b9df6978d6c14e52f9aeb0b8039cfc200d7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_operational_listing_authority\",\n \"path\": \"crates/event/src/operational_listing.rs\",\n \"byte_length\": 10307,\n \"sha256\": \"52e710db816c89c8d4b87c86541987f7447f2f7091c394c68d9cb98a27f90159\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_order_authority\",\n \"path\": \"crates/event/src/order.rs\",\n \"byte_length\": 60218,\n \"sha256\": \"4203fcc469612cac5c705884564e140b9fb076cd57079e22ed85275a8b936e50\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_reply_authority\",\n \"path\": \"crates/event/src/reply.rs\",\n \"byte_length\": 15581,\n \"sha256\": \"b0b83a1e96125c0892d932e9314519242a715fa8f46334aff765ffd248c91d9a\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_trade_validation_authority\",\n \"path\": \"crates/event/src/trade_validation.rs\",\n \"byte_length\": 4669,\n \"sha256\": \"1486f79bd1d0eadea6cc1b7646ce1f7f57ccade18334a3ea37286426676b9b98\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_relay_hint_authority\",\n \"path\": \"crates/event/src/relay_hint.rs\",\n \"byte_length\": 13598,\n \"sha256\": \"fb8b026eeccf51d78f20771c44223e7b48825aa0e3c760d6b3cb90148021a674\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_media_authority\",\n \"path\": \"crates/event/src/media.rs\",\n \"byte_length\": 3455,\n \"sha256\": \"10678af3a202d5367dbcf3bcdc0bf9fdf8d8fb89b045d7d3fb96b3cc195ab6f9\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_social_authority\",\n \"path\": \"crates/event/src/social.rs\",\n \"byte_length\": 6076,\n \"sha256\": \"a2dab19caad46eab14fac86e7c878a801a450d8ac374b0e728b71a5a224eef19\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_wire_facade\",\n \"path\": \"crates/event/src/wire.rs\",\n \"byte_length\": 68,\n \"sha256\": \"cb52f6006f7ecd862707d6b048f9fc407e0cd5ebcd3091b3c54e195ffa5cba64\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_wire_v1_authority\",\n \"path\": \"crates/event/src/wire/v1.rs\",\n \"byte_length\": 22198,\n \"sha256\": \"c818bc1f67e215948ba253c8c62b09ab788db9aeec9b6df8096014b55565cb8c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_public_surface\",\n \"path\": \"crates/event_codec/src/lib.rs\",\n \"byte_length\": 2448,\n \"sha256\": \"7d4b0040ad3971f34395b17cb1aa40617e9c2c9e1b4222676c388c3adaa47e07\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_verification_facade\",\n \"path\": \"crates/event_codec/src/verification.rs\",\n \"byte_length\": 253,\n \"sha256\": \"b49a32df605035c87f295c0a151140d43d2e588c5e11b05183e5fc92993dae0e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_verification_v1_authority\",\n \"path\": \"crates/event_codec/src/verification/v1.rs\",\n \"byte_length\": 6584,\n \"sha256\": \"72f64615bd6b6dc3b051579e3069b2213f3781dcc28e12f0b533c7d81b81b9b1\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_registry_v7_admission_authority\",\n \"path\": \"crates/event_codec/src/admission/registry_v7.rs\",\n \"byte_length\": 5228,\n \"sha256\": \"62da30cb6ef7d0ed2d43715a73bd529283e8ae8c12571bc5c68722cb400f17b8\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_admission_facade\",\n \"path\": \"crates/event_codec/src/admission.rs\",\n \"byte_length\": 21251,\n \"sha256\": \"25928e734e7b3688f92af806a12a13458c48fb47e94249f60f0226300d5da2b4\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_inbound_facade\",\n \"path\": \"crates/event_codec/src/profile/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/profile/inbound/registry_v7.rs\",\n \"byte_length\": 10347,\n \"sha256\": \"32111c0e0592229c11a93a3a8054e7b124b039451aa696a9abcb56df2a6608d3\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_post_inbound_facade\",\n \"path\": \"crates/event_codec/src/post/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_post_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/post/inbound/registry_v7.rs\",\n \"byte_length\": 15985,\n \"sha256\": \"e17083b0596e3a55994c399bc6272c0ebf04cabaa513260b3d45dd546f7f50ef\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_reply_inbound_facade\",\n \"path\": \"crates/event_codec/src/reply/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_reply_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/reply/inbound/registry_v7.rs\",\n \"byte_length\": 26662,\n \"sha256\": \"d1d11116ca27801b7e2f17da60900e6a9ca0b6f27ea9ee0bf19e97dbf24c0c32\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_comment_inbound_facade\",\n \"path\": \"crates/event_codec/src/comment/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_comment_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/comment/inbound/registry_v7.rs\",\n \"byte_length\": 53311,\n \"sha256\": \"c63fe853536b17bded6073f32b53434b60fc5123f911d01c642a6b3982f09c70\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_deletion_facade\",\n \"path\": \"crates/event_codec/src/deletion/mod.rs\",\n \"byte_length\": 115,\n \"sha256\": \"17d56f82ddb0a86bc97abbcf3e037fe460ea31fff2548f527be4bf004dac3a95\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_deletion_reconciliation_v1_authority\",\n \"path\": \"crates/event_codec/src/deletion/reconciliation_v1.rs\",\n \"byte_length\": 38028,\n \"sha256\": \"c6901f559e83700610595720c47a4d062078ae8411e1fc2fb952dd215b19dd90\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_error_authority\",\n \"path\": \"crates/event_codec/src/error.rs\",\n \"byte_length\": 3666,\n \"sha256\": \"174ce982bca37fac28d016c3ab3236441c9b31b2169ec94db6c9288b36c72849\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_admission_authority\",\n \"path\": \"crates/event_codec/src/food_availability/admission.rs\",\n \"byte_length\": 5681,\n \"sha256\": \"99809859090f5295572688d06bbb30dbe50524ba2c996de7ec5b26f6dd390643\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_authored_authority\",\n \"path\": \"crates/event_codec/src/food_availability/authored.rs\",\n \"byte_length\": 9724,\n \"sha256\": \"8673ec62ed3fc47b691efd9ca828643719803971e72b756c5b4603d409d0fba5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_inbound_facade\",\n \"path\": \"crates/event_codec/src/food_availability/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/food_availability/inbound/registry_v7.rs\",\n \"byte_length\": 26037,\n \"sha256\": \"92a7e75da3293967cec17a514479144c3c948a64542577dd58c7f07992968e4f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_job_traits_authority\",\n \"path\": \"crates/event_codec/src/job/traits.rs\",\n \"byte_length\": 4946,\n \"sha256\": \"1b3558a3196744005978dceddd33d3a72ad1ab8f50fb1cbfd997dcfe98bb9e39\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_job_encode_authority\",\n \"path\": \"crates/event_codec/src/job/encode.rs\",\n \"byte_length\": 1670,\n \"sha256\": \"5d6cae6309fcdd02deb7c751b5c451d257cf1900986391cb39cbb2bfd1ddb577\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_knowledge_verification_authority\",\n \"path\": \"crates/event_codec/src/knowledge/verification.rs\",\n \"byte_length\": 6986,\n \"sha256\": \"6f8a10ed262ce37f05acd9c89a1e37ca2fa99ce7da18407891e8abe228ee2349\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_operational_listing_tags_authority\",\n \"path\": \"crates/event_codec/src/operational_listing/tags.rs\",\n \"byte_length\": 50222,\n \"sha256\": \"55b6860bc6f4699dd47a49f8336764e9db78aafb7c32849102dedeb96804b373\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_order_decode_authority\",\n \"path\": \"crates/event_codec/src/order/decode.rs\",\n \"byte_length\": 42667,\n \"sha256\": \"033d9465bc041d205eab3f820572b719a35651340dcb50bdce7c60fabee5f6e1\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_facade\",\n \"path\": \"crates/event_codec/src/profile/mod.rs\",\n \"byte_length\": 1456,\n \"sha256\": \"06b890da54580e2ec68f7e729281b7c3b650ac0a95a4fcb0db3c6cdaa591a7ef\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_tag_builders_authority\",\n \"path\": \"crates/event_codec/src/tag_builders.rs\",\n \"byte_length\": 9232,\n \"sha256\": \"bd81ccf04fd72358331b48eddcde087a95e115c5bd90c05fd9332644979ad5e6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_trade_facade\",\n \"path\": \"crates/event_codec/src/trade/mod.rs\",\n \"byte_length\": 21472,\n \"sha256\": \"10cee4b6cd6429ac9eb00327a521bcd0982fae4de98bda77e4728fda002965d3\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_dependency_authority\",\n \"path\": \"crates/event_store/Cargo.toml\",\n \"byte_length\": 1570,\n \"sha256\": \"e2116eb02eb2b18b21db7351f29a1efeffe11ce4ab9bb7c85a3f3e7f2e56aca4\",\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\": 19458,\n \"sha256\": \"3d87df984af6ae5decf7ca8c3a8d5422be6c647e6a05490225b6b2037bf3701b\",\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\": 32070,\n \"sha256\": \"2cdbf6d1a4e0fa6680f45f02758513509339a7cf3a2387e824fb73b0edf749a4\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_reconciliation_v1_model\",\n \"path\": \"crates/event_store/src/model/reconciliation_v1.rs\",\n \"byte_length\": 10446,\n \"sha256\": \"475b7b840bffdae7e3f7a31f5b940b9dfa579eaa1cac640729aaaeadabf83ba6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_reconciliation_v1_ingest_model\",\n \"path\": \"crates/event_store/src/model/ingest_reconciliation_v1.rs\",\n \"byte_length\": 1588,\n \"sha256\": \"6117e797674c35bb1ccebffbc6a8c0108bfc38c7c9f82607066dfd802b8f0734\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"addressable_transition_feed_model\",\n \"path\": \"crates/event_store/src/model/addressable_transition_feed_v1.rs\",\n \"byte_length\": 22229,\n \"sha256\": \"e651952d73ed0a29d2b137076f56f699beada205ac84ed8a96834e86e343fa78\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"current_visibility_model\",\n \"path\": \"crates/event_store/src/model/current_visibility_v1.rs\",\n \"byte_length\": 5634,\n \"sha256\": \"d64429bc7985231e923c1c3e5295d94270a817dd5dc96693f35dfdf2dc398e4f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"food_projection_model\",\n \"path\": \"crates/event_store/src/model/food_availability_projection_v1.rs\",\n \"byte_length\": 17108,\n \"sha256\": \"67861a966d674efbc40f0b0433db2ec006048ff923f6261df4161e2ddba717b5\",\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\": 184833,\n \"sha256\": \"3ca802cb7a8444c8512b2be1390a019281704316a430fb9b75a8ad2cad358a07\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"nip09_successor_result_vector_executor\",\n \"path\": \"crates/event_store/tests/support/nip09_reconciliation_v1_result_vector_v2.rs\",\n \"byte_length\": 18205,\n \"sha256\": \"c632beee70dc777b8dd2a4f88cadb55296fee7aa5742e6e2c9f6d49f26ae2c78\",\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\": 393218,\n \"sha256\": \"64565c3bc043779e1c2f26d9761901b109b4acab0f48c2021102c0e4e1f1f726\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"addressable_transition_feed_store\",\n \"path\": \"crates/event_store/src/store/addressable_transition_feed_v1.rs\",\n \"byte_length\": 40209,\n \"sha256\": \"2cebcca9602633652a79e7041d18d3a7d3feb1388a98f4f68137b9814efcedfa\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"current_visibility_store\",\n \"path\": \"crates/event_store/src/store/current_visibility_v1.rs\",\n \"byte_length\": 15737,\n \"sha256\": \"aa5d1bff7a5368cbac2b37906bb40f54bfc8aa6906bab34369569fdd105bf899\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"food_projection_store\",\n \"path\": \"crates/event_store/src/store/food_availability_projection_v1.rs\",\n \"byte_length\": 48919,\n \"sha256\": \"3a30da308ef863b806ed63d1cb65ac80f6a946a71821af84a0c595330491757e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_post_core_v1_extension\",\n \"path\": \"crates/event_store/src/store/post_core_extensions_v1.rs\",\n \"byte_length\": 6569,\n \"sha256\": \"f5bd8ddb45e1b2144895bd8da737fc92db051be1844ce7e8047a32b47376ce37\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_post_core_v1_storage\",\n \"path\": \"crates/event_store/src/store/post_core_storage_v1.rs\",\n \"byte_length\": 16538,\n \"sha256\": \"fcd6546c23a6cba12b70d92728d19b6ee5d43174b83495f820348b77efa33aab\",\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\": 29950,\n \"sha256\": \"c72aaff06e4f35d0b4523c6625e83345879f9e15b9fe9563dccf589e5d01e277\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_protocol_storage\",\n \"path\": \"crates/event_store/src/store/protocol_storage_v1.rs\",\n \"byte_length\": 10835,\n \"sha256\": \"c82179b9f57968191f3e71dd008cc701787c62715ada74090eeecaa3b213076d\",\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\": 51849,\n \"sha256\": \"db43df5849c811d767a87bfa7884ce499400d0b169734e18242542a4415b3a51\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_food_result_vector_executor\",\n \"path\": \"crates/event_store/tests/food_availability_projection_v1_result_vector.rs\",\n \"byte_length\": 34046,\n \"sha256\": \"776903c6431ff07f26c6ad6b713db5628efce1a72f34d86de6e47d4404fa3a6d\",\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\": 39149,\n \"sha256\": \"3d1bba3980b80698d2a21e26caf7af6fe4d9dc4a7fbabc6e406b5d33928b457f\",\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\": 198991,\n \"sha256\": \"36fd3d8b5dda3b0855a06a47dae14cae7f4cc84aaca9902c31477c218859fccc\",\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\": 842402,\n \"sha256\": \"4abb141771cfa257440dba7ebeae21f5ad1f9856cc0d5f6437ba68614d997810\",\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\": 199270,\n \"sha256\": \"65b83a3ee1a700527d15c7403ca042cf2aaa4cd8935a2f8d2ab190c491a815bd\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"contract_command_authority\",\n \"path\": \"tools/xtask/src/contract.rs\",\n \"byte_length\": 508374,\n \"sha256\": \"c498f6fda5e595c7165465a9f261b45acc7ef47762e1fc04fd94026f9ecf2167\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"dto_root_generation_authority\",\n \"path\": \"tools/xtask/src/dto_roots.rs\",\n \"byte_length\": 35940,\n \"sha256\": \"a899a5695d7533c151d03477c4bd697a6e55c47a4980549724ac42046af694f5\",\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\": 16426,\n \"sha256\": \"abc24896c6c740c10811a3e003ec4be8ebdb376a7b6b01445bfa7a5889f094a7\",\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\": \"96ea98a5abf3348b61565954cd34f2c622411d8dd34205ef04134bbe0e3d3f2b\",\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\": \"02dfe1b450fbdac16e718888215b4dd5c85d8975440fa21e8f439fb24c2b2990\",\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\": \"ab2724188f8d08c897eebea2533a635e7c74282a25e84e4c0c37e78b08837a43\",\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\": \"074f85b663444ac150239ecd8441ea4a96ad83a798a55e22d2e5e2f7ee943a8c\",\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\": \"02dfe1b450fbdac16e718888215b4dd5c85d8975440fa21e8f439fb24c2b2990\",\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\": 12440,\n \"sha256\": \"8981f78d3ea85454a8cf7be156b3eef5659b399f1631d7c1068e7c336988070d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_currency_value_authority\",\n \"path\": \"crates/core/src/currency.rs\",\n \"byte_length\": 4142,\n \"sha256\": \"42e6da2d8d2fdd6955dc2d83e98dd00266e02bc910b69923b117662c05089d14\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_decimal_value_authority\",\n \"path\": \"crates/core/src/decimal.rs\",\n \"byte_length\": 7839,\n \"sha256\": \"4b1d681a92d7a9e074bee7e1f20eb1499bb05bfc6528a6c9ba69fa7d00416550\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_money_value_authority\",\n \"path\": \"crates/core/src/money.rs\",\n \"byte_length\": 8025,\n \"sha256\": \"3f30bc21e21951a62fdc5d4033736ed42a883df590e8403940775bd2edfeebc5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_percent_value_authority\",\n \"path\": \"crates/core/src/percent.rs\",\n \"byte_length\": 2652,\n \"sha256\": \"42ceab109881329f3539d06a0ee0381ab4359985fe185a18d58a9c9558c5eb7f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_quantity_value_authority\",\n \"path\": \"crates/core/src/quantity.rs\",\n \"byte_length\": 6785,\n \"sha256\": \"d14e619da3829cdaf3ca7385fb892d330c286c1e21455c135c37518cbb588b5f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_quantity_price_value_authority\",\n \"path\": \"crates/core/src/quantity_price.rs\",\n \"byte_length\": 7061,\n \"sha256\": \"d60f70377099470ed283f45868a5119d7bb46143cb250b5082a4c038ba7f6cdc\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"core_unit_value_authority\",\n \"path\": \"crates/core/src/unit.rs\",\n \"byte_length\": 10023,\n \"sha256\": \"550e9582b6a5290aac3f637b83853b21fefcbab92c432d067c83448f4b2fe3e9\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_public_surface\",\n \"path\": \"crates/blossom/src/lib.rs\",\n \"byte_length\": 510,\n \"sha256\": \"a4dfcbd193457c50c1b0fbfc91bb547981ecd3a6e23cfc6f1030edfb511dc58c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_authorization_authority\",\n \"path\": \"crates/blossom/src/authorization.rs\",\n \"byte_length\": 39360,\n \"sha256\": \"461947b30516315a342b3b5697599f701d27050888f29f67f5d7a7ad4afa4c28\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_descriptor_authority\",\n \"path\": \"crates/blossom/src/descriptor.rs\",\n \"byte_length\": 13702,\n \"sha256\": \"b2a4ffa760256e1316f70e012d200e2b5f4afd8ede771b85a5147f96b247f599\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_error_authority\",\n \"path\": \"crates/blossom/src/error.rs\",\n \"byte_length\": 17229,\n \"sha256\": \"02af55beacf437040be17d1fc3271d6e2a62915f656ec2dbe06247deef83f95a\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_hash_authority\",\n \"path\": \"crates/blossom/src/hash.rs\",\n \"byte_length\": 11006,\n \"sha256\": \"45eca0d81ac0f46c305a32f81aafcdd90b14679d0614f72862289a6e5d4cb08f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_media_type_authority\",\n \"path\": \"crates/blossom/src/media_type.rs\",\n \"byte_length\": 2368,\n \"sha256\": \"69db5c0f9fcdd7dbe1f22daa499f65603ae4ce198083dab2c73a36813fa18a46\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"blossom_url_authority\",\n \"path\": \"crates/blossom/src/url.rs\",\n \"byte_length\": 14580,\n \"sha256\": \"342c995fcf620e5fb32461a7d8276f5668ba2662890bd32d12780cc9121c6451\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_public_surface\",\n \"path\": \"crates/event/src/lib.rs\",\n \"byte_length\": 1892,\n \"sha256\": \"5d609b963a9b8db18ef96a10f394617413734d2631774d3296e6d8fc029cb02c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_contract_facade\",\n \"path\": \"crates/event/src/contract.rs\",\n \"byte_length\": 208,\n \"sha256\": \"27466bf36461071931f391c60646a13f7781d19584583166cc54c0eece76d010\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_contract_registry_v7_authority\",\n \"path\": \"crates/event/src/contract/registry_v7.rs\",\n \"byte_length\": 145805,\n \"sha256\": \"0a62603f6fc05dc9f758561cf7da258c676ada810ceaeca7fb151364a5c83d62\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_envelope_authority\",\n \"path\": \"crates/event/src/envelope.rs\",\n \"byte_length\": 29310,\n \"sha256\": \"29f8d8c4b17c01cb5a8c7f59e4ce52e134180e0e6f37d265063d278b8f2ff26e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_verification_typestate_authority\",\n \"path\": \"crates/event/src/verification.rs\",\n \"byte_length\": 9400,\n \"sha256\": \"417acb2ce670d266b1fa4fcafd6b48a910218deab38f57fb8b942056db76f94d\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_admission_typestate_authority\",\n \"path\": \"crates/event/src/admission.rs\",\n \"byte_length\": 7052,\n \"sha256\": \"62bd2ceb0f434946fdfc2b81f4efb13738676a29a6936c23a427e43aadf2d9cb\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_head_facade\",\n \"path\": \"crates/event/src/event_head.rs\",\n \"byte_length\": 97,\n \"sha256\": \"f761ff3e74c4f5e1e28381db00ce698c633ff048669b22984d14a587482e8e83\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_head_v1_authority\",\n \"path\": \"crates/event/src/event_head/v1.rs\",\n \"byte_length\": 6849,\n \"sha256\": \"9f4144d8d240023cf493ce0b538ade4c16dc44204d6b5f2797152caf6f9e7dba\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_ids_authority\",\n \"path\": \"crates/event/src/id.rs\",\n \"byte_length\": 48381,\n \"sha256\": \"a08fe3873815453a03318a706e2fa98a8a6728ec69d24368a87ec60025566fe0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_trade_authority\",\n \"path\": \"crates/event/src/trade.rs\",\n \"byte_length\": 65549,\n \"sha256\": \"f818a7287ed82de3fb9ef1d973f0fb18d84b30eb4827ddc576ee502dd980145f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_kinds_authority\",\n \"path\": \"crates/event/src/kinds.rs\",\n \"byte_length\": 34961,\n \"sha256\": \"8b3ce6193cab1f7e1587d0c1b2880a81b0aa43c77d89671b602772db37edcebf\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_tags_authority\",\n \"path\": \"crates/event/src/tags.rs\",\n \"byte_length\": 4530,\n \"sha256\": \"cb8f12a639fc72d9238e32495d9e67e928e6627fb8c94ec0a58c5d95e7373cd6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_draft_authority\",\n \"path\": \"crates/event/src/draft.rs\",\n \"byte_length\": 51150,\n \"sha256\": \"ecc619aae28d688d13f35467398f17766b60f26c2bf3616d772ce65b7fa4fb53\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_calendar_authority\",\n \"path\": \"crates/event/src/calendar.rs\",\n \"byte_length\": 97992,\n \"sha256\": \"73e79d61ee175cb46e6123e1d28239252ddf0ad094dc1113bdb1286b63b88d57\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_classified_listing_authority\",\n \"path\": \"crates/event/src/classified_listing.rs\",\n \"byte_length\": 7956,\n \"sha256\": \"ac58484b87c7712c81f50f884d1c0dd60938571aa5f6f05d555191f529a4c2b0\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_profile_authority\",\n \"path\": \"crates/event/src/profile.rs\",\n \"byte_length\": 17011,\n \"sha256\": \"572bfe3b6f1711d109db445077f0a8453cad3f021cc0638f79201b618e16b978\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_post_authority\",\n \"path\": \"crates/event/src/post.rs\",\n \"byte_length\": 19968,\n \"sha256\": \"a822cd51eff9cbaa39db998cc5c90d117f7a983f0fe2d42d42118cb00e95982c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_comment_authority\",\n \"path\": \"crates/event/src/comment.rs\",\n \"byte_length\": 34745,\n \"sha256\": \"24b7fda13229f21cee5cef2a9941e3aaafdbc486b19ed42731b0b6ee37c28703\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_food_availability_authority\",\n \"path\": \"crates/event/src/food_availability.rs\",\n \"byte_length\": 42829,\n \"sha256\": \"52472c07eb0855d884c60755dc3a3e1a963793451d707e51f769f2d78384f318\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_deletion_authority\",\n \"path\": \"crates/event/src/deletion.rs\",\n \"byte_length\": 30022,\n \"sha256\": \"8c3f2e32407520a8e8242c1293af32613c648fb76218b8003a18929ac0b3811f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_dto_authority\",\n \"path\": \"crates/event/src/dto.rs\",\n \"byte_length\": 5038,\n \"sha256\": \"9e228c95ff6ff33f99441d8682781fd0a1c4d3f1db24284a43985dcbac3ba136\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_farm_crdt_authority\",\n \"path\": \"crates/event/src/farm_crdt.rs\",\n \"byte_length\": 21118,\n \"sha256\": \"cec265ac9c42b59a14be4eb96924d26a83477c27291f667f23e6e47a64b6b2c7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_knowledge_authority\",\n \"path\": \"crates/event/src/knowledge.rs\",\n \"byte_length\": 54624,\n \"sha256\": \"3d55ff88a4e30d5d605f9ae4b2e96b9df6978d6c14e52f9aeb0b8039cfc200d7\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_operational_listing_authority\",\n \"path\": \"crates/event/src/operational_listing.rs\",\n \"byte_length\": 10307,\n \"sha256\": \"52e710db816c89c8d4b87c86541987f7447f2f7091c394c68d9cb98a27f90159\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_order_authority\",\n \"path\": \"crates/event/src/order.rs\",\n \"byte_length\": 60218,\n \"sha256\": \"4203fcc469612cac5c705884564e140b9fb076cd57079e22ed85275a8b936e50\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_reply_authority\",\n \"path\": \"crates/event/src/reply.rs\",\n \"byte_length\": 15581,\n \"sha256\": \"b0b83a1e96125c0892d932e9314519242a715fa8f46334aff765ffd248c91d9a\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_trade_validation_authority\",\n \"path\": \"crates/event/src/trade_validation.rs\",\n \"byte_length\": 4669,\n \"sha256\": \"1486f79bd1d0eadea6cc1b7646ce1f7f57ccade18334a3ea37286426676b9b98\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_relay_hint_authority\",\n \"path\": \"crates/event/src/relay_hint.rs\",\n \"byte_length\": 13598,\n \"sha256\": \"fb8b026eeccf51d78f20771c44223e7b48825aa0e3c760d6b3cb90148021a674\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_media_authority\",\n \"path\": \"crates/event/src/media.rs\",\n \"byte_length\": 3455,\n \"sha256\": \"10678af3a202d5367dbcf3bcdc0bf9fdf8d8fb89b045d7d3fb96b3cc195ab6f9\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_social_authority\",\n \"path\": \"crates/event/src/social.rs\",\n \"byte_length\": 6076,\n \"sha256\": \"a2dab19caad46eab14fac86e7c878a801a450d8ac374b0e728b71a5a224eef19\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_wire_facade\",\n \"path\": \"crates/event/src/wire.rs\",\n \"byte_length\": 68,\n \"sha256\": \"cb52f6006f7ecd862707d6b048f9fc407e0cd5ebcd3091b3c54e195ffa5cba64\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_wire_v1_authority\",\n \"path\": \"crates/event/src/wire/v1.rs\",\n \"byte_length\": 22198,\n \"sha256\": \"c818bc1f67e215948ba253c8c62b09ab788db9aeec9b6df8096014b55565cb8c\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_public_surface\",\n \"path\": \"crates/event_codec/src/lib.rs\",\n \"byte_length\": 2448,\n \"sha256\": \"7d4b0040ad3971f34395b17cb1aa40617e9c2c9e1b4222676c388c3adaa47e07\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_verification_facade\",\n \"path\": \"crates/event_codec/src/verification.rs\",\n \"byte_length\": 253,\n \"sha256\": \"b49a32df605035c87f295c0a151140d43d2e588c5e11b05183e5fc92993dae0e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_verification_v1_authority\",\n \"path\": \"crates/event_codec/src/verification/v1.rs\",\n \"byte_length\": 6584,\n \"sha256\": \"72f64615bd6b6dc3b051579e3069b2213f3781dcc28e12f0b533c7d81b81b9b1\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_registry_v7_admission_authority\",\n \"path\": \"crates/event_codec/src/admission/registry_v7.rs\",\n \"byte_length\": 5228,\n \"sha256\": \"62da30cb6ef7d0ed2d43715a73bd529283e8ae8c12571bc5c68722cb400f17b8\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_admission_facade\",\n \"path\": \"crates/event_codec/src/admission.rs\",\n \"byte_length\": 21251,\n \"sha256\": \"25928e734e7b3688f92af806a12a13458c48fb47e94249f60f0226300d5da2b4\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_inbound_facade\",\n \"path\": \"crates/event_codec/src/profile/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/profile/inbound/registry_v7.rs\",\n \"byte_length\": 10347,\n \"sha256\": \"32111c0e0592229c11a93a3a8054e7b124b039451aa696a9abcb56df2a6608d3\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_post_inbound_facade\",\n \"path\": \"crates/event_codec/src/post/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_post_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/post/inbound/registry_v7.rs\",\n \"byte_length\": 15985,\n \"sha256\": \"e17083b0596e3a55994c399bc6272c0ebf04cabaa513260b3d45dd546f7f50ef\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_reply_inbound_facade\",\n \"path\": \"crates/event_codec/src/reply/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_reply_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/reply/inbound/registry_v7.rs\",\n \"byte_length\": 26662,\n \"sha256\": \"d1d11116ca27801b7e2f17da60900e6a9ca0b6f27ea9ee0bf19e97dbf24c0c32\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_comment_inbound_facade\",\n \"path\": \"crates/event_codec/src/comment/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_comment_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/comment/inbound/registry_v7.rs\",\n \"byte_length\": 53311,\n \"sha256\": \"c63fe853536b17bded6073f32b53434b60fc5123f911d01c642a6b3982f09c70\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_deletion_facade\",\n \"path\": \"crates/event_codec/src/deletion/mod.rs\",\n \"byte_length\": 115,\n \"sha256\": \"17d56f82ddb0a86bc97abbcf3e037fe460ea31fff2548f527be4bf004dac3a95\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_deletion_reconciliation_v1_authority\",\n \"path\": \"crates/event_codec/src/deletion/reconciliation_v1.rs\",\n \"byte_length\": 38028,\n \"sha256\": \"c6901f559e83700610595720c47a4d062078ae8411e1fc2fb952dd215b19dd90\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_error_authority\",\n \"path\": \"crates/event_codec/src/error.rs\",\n \"byte_length\": 3666,\n \"sha256\": \"174ce982bca37fac28d016c3ab3236441c9b31b2169ec94db6c9288b36c72849\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_admission_authority\",\n \"path\": \"crates/event_codec/src/food_availability/admission.rs\",\n \"byte_length\": 5681,\n \"sha256\": \"99809859090f5295572688d06bbb30dbe50524ba2c996de7ec5b26f6dd390643\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_authored_authority\",\n \"path\": \"crates/event_codec/src/food_availability/authored.rs\",\n \"byte_length\": 9724,\n \"sha256\": \"8673ec62ed3fc47b691efd9ca828643719803971e72b756c5b4603d409d0fba5\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_inbound_facade\",\n \"path\": \"crates/event_codec/src/food_availability/inbound.rs\",\n \"byte_length\": 86,\n \"sha256\": \"9994cbca9dcc7450ad133b6b927e7c06bee08ef813652452cc1e56a284c1be10\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_food_registry_v7_authority\",\n \"path\": \"crates/event_codec/src/food_availability/inbound/registry_v7.rs\",\n \"byte_length\": 26037,\n \"sha256\": \"92a7e75da3293967cec17a514479144c3c948a64542577dd58c7f07992968e4f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_job_traits_authority\",\n \"path\": \"crates/event_codec/src/job/traits.rs\",\n \"byte_length\": 4946,\n \"sha256\": \"1b3558a3196744005978dceddd33d3a72ad1ab8f50fb1cbfd997dcfe98bb9e39\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_job_encode_authority\",\n \"path\": \"crates/event_codec/src/job/encode.rs\",\n \"byte_length\": 1670,\n \"sha256\": \"5d6cae6309fcdd02deb7c751b5c451d257cf1900986391cb39cbb2bfd1ddb577\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_knowledge_verification_authority\",\n \"path\": \"crates/event_codec/src/knowledge/verification.rs\",\n \"byte_length\": 6986,\n \"sha256\": \"6f8a10ed262ce37f05acd9c89a1e37ca2fa99ce7da18407891e8abe228ee2349\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_operational_listing_tags_authority\",\n \"path\": \"crates/event_codec/src/operational_listing/tags.rs\",\n \"byte_length\": 50222,\n \"sha256\": \"55b6860bc6f4699dd47a49f8336764e9db78aafb7c32849102dedeb96804b373\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_order_decode_authority\",\n \"path\": \"crates/event_codec/src/order/decode.rs\",\n \"byte_length\": 42667,\n \"sha256\": \"033d9465bc041d205eab3f820572b719a35651340dcb50bdce7c60fabee5f6e1\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_profile_facade\",\n \"path\": \"crates/event_codec/src/profile/mod.rs\",\n \"byte_length\": 1456,\n \"sha256\": \"06b890da54580e2ec68f7e729281b7c3b650ac0a95a4fcb0db3c6cdaa591a7ef\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_tag_builders_authority\",\n \"path\": \"crates/event_codec/src/tag_builders.rs\",\n \"byte_length\": 9232,\n \"sha256\": \"bd81ccf04fd72358331b48eddcde087a95e115c5bd90c05fd9332644979ad5e6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_codec_trade_facade\",\n \"path\": \"crates/event_codec/src/trade/mod.rs\",\n \"byte_length\": 21472,\n \"sha256\": \"10cee4b6cd6429ac9eb00327a521bcd0982fae4de98bda77e4728fda002965d3\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_dependency_authority\",\n \"path\": \"crates/event_store/Cargo.toml\",\n \"byte_length\": 1570,\n \"sha256\": \"e2116eb02eb2b18b21db7351f29a1efeffe11ce4ab9bb7c85a3f3e7f2e56aca4\",\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\": 19458,\n \"sha256\": \"3d87df984af6ae5decf7ca8c3a8d5422be6c647e6a05490225b6b2037bf3701b\",\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\": 32070,\n \"sha256\": \"2cdbf6d1a4e0fa6680f45f02758513509339a7cf3a2387e824fb73b0edf749a4\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_reconciliation_v1_model\",\n \"path\": \"crates/event_store/src/model/reconciliation_v1.rs\",\n \"byte_length\": 10446,\n \"sha256\": \"475b7b840bffdae7e3f7a31f5b940b9dfa579eaa1cac640729aaaeadabf83ba6\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"event_store_reconciliation_v1_ingest_model\",\n \"path\": \"crates/event_store/src/model/ingest_reconciliation_v1.rs\",\n \"byte_length\": 1588,\n \"sha256\": \"6117e797674c35bb1ccebffbc6a8c0108bfc38c7c9f82607066dfd802b8f0734\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"addressable_transition_feed_model\",\n \"path\": \"crates/event_store/src/model/addressable_transition_feed_v1.rs\",\n \"byte_length\": 22229,\n \"sha256\": \"e651952d73ed0a29d2b137076f56f699beada205ac84ed8a96834e86e343fa78\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"current_visibility_model\",\n \"path\": \"crates/event_store/src/model/current_visibility_v1.rs\",\n \"byte_length\": 5634,\n \"sha256\": \"d64429bc7985231e923c1c3e5295d94270a817dd5dc96693f35dfdf2dc398e4f\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"food_projection_model\",\n \"path\": \"crates/event_store/src/model/food_availability_projection_v1.rs\",\n \"byte_length\": 17108,\n \"sha256\": \"67861a966d674efbc40f0b0433db2ec006048ff923f6261df4161e2ddba717b5\",\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\": 184833,\n \"sha256\": \"3ca802cb7a8444c8512b2be1390a019281704316a430fb9b75a8ad2cad358a07\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"nip09_successor_result_vector_executor\",\n \"path\": \"crates/event_store/tests/support/nip09_reconciliation_v1_result_vector_v2.rs\",\n \"byte_length\": 18205,\n \"sha256\": \"c632beee70dc777b8dd2a4f88cadb55296fee7aa5742e6e2c9f6d49f26ae2c78\",\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\": 393218,\n \"sha256\": \"64565c3bc043779e1c2f26d9761901b109b4acab0f48c2021102c0e4e1f1f726\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"addressable_transition_feed_store\",\n \"path\": \"crates/event_store/src/store/addressable_transition_feed_v1.rs\",\n \"byte_length\": 40209,\n \"sha256\": \"2cebcca9602633652a79e7041d18d3a7d3feb1388a98f4f68137b9814efcedfa\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"current_visibility_store\",\n \"path\": \"crates/event_store/src/store/current_visibility_v1.rs\",\n \"byte_length\": 15737,\n \"sha256\": \"aa5d1bff7a5368cbac2b37906bb40f54bfc8aa6906bab34369569fdd105bf899\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"food_projection_store\",\n \"path\": \"crates/event_store/src/store/food_availability_projection_v1.rs\",\n \"byte_length\": 48919,\n \"sha256\": \"3a30da308ef863b806ed63d1cb65ac80f6a946a71821af84a0c595330491757e\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_post_core_v1_extension\",\n \"path\": \"crates/event_store/src/store/post_core_extensions_v1.rs\",\n \"byte_length\": 6569,\n \"sha256\": \"f5bd8ddb45e1b2144895bd8da737fc92db051be1844ce7e8047a32b47376ce37\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_post_core_v1_storage\",\n \"path\": \"crates/event_store/src/store/post_core_storage_v1.rs\",\n \"byte_length\": 16538,\n \"sha256\": \"fcd6546c23a6cba12b70d92728d19b6ee5d43174b83495f820348b77efa33aab\",\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\": 29950,\n \"sha256\": \"c72aaff06e4f35d0b4523c6625e83345879f9e15b9fe9563dccf589e5d01e277\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_protocol_storage\",\n \"path\": \"crates/event_store/src/store/protocol_storage_v1.rs\",\n \"byte_length\": 10835,\n \"sha256\": \"c82179b9f57968191f3e71dd008cc701787c62715ada74090eeecaa3b213076d\",\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\": 51849,\n \"sha256\": \"db43df5849c811d767a87bfa7884ce499400d0b169734e18242542a4415b3a51\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"predecessor_food_result_vector_executor\",\n \"path\": \"crates/event_store/tests/food_availability_projection_v1_result_vector.rs\",\n \"byte_length\": 34046,\n \"sha256\": \"776903c6431ff07f26c6ad6b713db5628efce1a72f34d86de6e47d4404fa3a6d\",\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\": 39149,\n \"sha256\": \"3d1bba3980b80698d2a21e26caf7af6fe4d9dc4a7fbabc6e406b5d33928b457f\",\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\": 198991,\n \"sha256\": \"36fd3d8b5dda3b0855a06a47dae14cae7f4cc84aaca9902c31477c218859fccc\",\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\": 842402,\n \"sha256\": \"4abb141771cfa257440dba7ebeae21f5ad1f9856cc0d5f6437ba68614d997810\",\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\": 199270,\n \"sha256\": \"65b83a3ee1a700527d15c7403ca042cf2aaa4cd8935a2f8d2ab190c491a815bd\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"contract_command_authority\",\n \"path\": \"tools/xtask/src/contract.rs\",\n \"byte_length\": 508073,\n \"sha256\": \"26d1825a0d7a4a3bb983478f2ef87dc228cbfb68f794bb52864e34a62ef1eead\",\n \"hash_algorithm\": \"sha256_bytes_v1\"\n },\n {\n \"role\": \"dto_root_generation_authority\",\n \"path\": \"tools/xtask/src/dto_roots.rs\",\n \"byte_length\": 35940,\n \"sha256\": \"a899a5695d7533c151d03477c4bd697a6e55c47a4980549724ac42046af694f5\",\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\": 16426,\n \"sha256\": \"abc24896c6c740c10811a3e003ec4be8ebdb376a7b6b01445bfa7a5889f094a7\",\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 = 38397;
pub(crate) const SOURCE_MAINTENANCE_MANIFEST_SHA256: &str =
- "032aab678a257acd2215d631b53d4883b41c74d023725d3ccd0518d8d5858a86";
+ "ef7894006bc64f8b72718708f16babe3302209c6b1e74465def57d6b1862a9b6";
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/crates/net/src/nostr_client/events/post.rs b/crates/net/src/nostr_client/events/post.rs
@@ -1,16 +1,15 @@
use crate::error::{NetError, Result};
use radroots_event::{post::AuthoredUpdate, post::reply::AuthoredNip10Reply};
use radroots_event_codec::{parsed::RadrootsParsedData, post::decode::LegacyPost};
-use radroots_nostr::events::post::radroots_nostr_build_update_event;
-use radroots_nostr::events::post::radroots_nostr_post_events_filter;
-use radroots_nostr::events::reply::radroots_nostr_build_nip10_reply_event;
+use radroots_nostr::event::build_nip10_reply;
+use radroots_nostr::event::build_update;
+use radroots_nostr::event::post_filter;
use crate::nostr_client::manager::NostrClientManager;
impl NostrClientManager {
pub async fn publish_update_event(&self, update: &AuthoredUpdate) -> Result<String> {
- let builder =
- radroots_nostr_build_update_event(update).map_err(|e| NetError::Msg(e.to_string()))?;
+ let builder = build_update(update).map_err(|e| NetError::Msg(e.to_string()))?;
let event = builder
.sign_with_keys(&self.inner.keys)
.map_err(|error| NetError::Msg(error.to_string()))?;
@@ -30,8 +29,7 @@ impl NostrClientManager {
}
pub async fn publish_nip10_reply_event(&self, reply: &AuthoredNip10Reply) -> Result<String> {
- let builder = radroots_nostr_build_nip10_reply_event(reply)
- .map_err(|e| NetError::Msg(e.to_string()))?;
+ let builder = build_nip10_reply(reply).map_err(|e| NetError::Msg(e.to_string()))?;
let event = builder
.sign_with_keys(&self.inner.keys)
.map_err(|error| NetError::Msg(error.to_string()))?;
@@ -58,7 +56,7 @@ impl NostrClientManager {
limit: u16,
since_unix: Option<u64>,
) -> Result<Vec<RadrootsParsedData<LegacyPost>>> {
- let filter = radroots_nostr_post_events_filter(Some(limit), since_unix);
+ let filter = post_filter(Some(limit), since_unix);
let events = self
.inner
.client
@@ -67,7 +65,7 @@ impl NostrClientManager {
.map_err(|error| NetError::Msg(error.to_string()))?;
Ok(events
.into_iter()
- .map(|event| radroots_nostr::event_adapters::to_post_event_metadata(&event))
+ .map(|event| radroots_nostr::event::to_post_event_metadata(&event))
.collect())
}
diff --git a/crates/net/src/nostr_client/events/profile.rs b/crates/net/src/nostr_client/events/profile.rs
@@ -33,7 +33,7 @@ impl NostrClientManager {
.filter(|event| event.kind == RadrootsNostrKind::Metadata)
.max_by_key(|event| event.created_at);
if let Some(e) = ev {
- if let Some(meta) = radroots_nostr::event_adapters::to_profile_event_metadata(&e) {
+ if let Some(meta) = radroots_nostr::event::to_profile_event_metadata(&e) {
return Ok(Some(meta));
}
return Err(NetError::Msg(
diff --git a/crates/net/src/nostr_client/manager.rs b/crates/net/src/nostr_client/manager.rs
@@ -4,7 +4,7 @@ use tokio::runtime::Handle;
use super::inner::Inner;
use nostr::Keys as RadrootsNostrKeys;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::events::post::radroots_nostr_post_events_filter;
+use radroots_nostr::event::post_filter;
#[derive(Clone)]
pub struct NostrClientManager {
@@ -44,7 +44,7 @@ impl NostrClientManager {
let mut since =
since_unix.unwrap_or_else(|| RadrootsNostrTimestamp::now().as_secs());
loop {
- let filter = radroots_nostr_post_events_filter(None, Some(since));
+ let filter = post_filter(None, Some(since));
let mut stream = match inner
.client
@@ -59,7 +59,7 @@ impl NostrClientManager {
};
while let Some(event) = stream.next().await {
- let meta = radroots_nostr::event_adapters::to_post_event_metadata(&event);
+ let meta = radroots_nostr::event::to_post_event_metadata(&event);
let ts = event.created_at.as_secs();
since = ts.saturating_add(1);
let _ = inner.post_events_tx.send(meta);
diff --git a/crates/nostr/COMPATIBILITY.md b/crates/nostr/COMPATIBILITY.md
@@ -0,0 +1,20 @@
+# Superseded surface retirement
+
+`radroots_nostr` remains `publish = false` while Release V1 migration is in
+progress. Step 133 removed its public `error`, `events`, `types`, `util`,
+`codec_adapters`, `job_adapter`, `event_adapters`, `event_verify`, and
+`draft_signing` paths, the unsupported `codec` feature, and every public
+`radroots_nostr_*` item. The durable surface is limited to the seven modules
+and single root `Error` export in the Release V1 package charter.
+
+An all-first-party source search also found separate OSS capsules that still
+reference the predecessor `radroots_nostr::prelude` API. Those capsules are
+outside the authorized `oss/lib` and `oss/sdk` crate-surface edit boundary and
+already require their own upstream cutover; no compatibility path was restored
+for them here. No new consumer may adopt any retired path.
+
+Step 313 is the exact final pre-release audit. It must repeat the all-first-party
+search, confirm every separate capsule has migrated or pinned a compatible
+upstream library revision, remove this migration record, regenerate the public
+API baseline, and pass the package-realistic downstream matrix before Release
+V1 approval.
diff --git a/crates/nostr/Cargo.toml b/crates/nostr/Cargo.toml
@@ -27,13 +27,12 @@ std = [
"radroots_identity/std",
]
blossom = ["std", "dep:base64", "dep:radroots_blossom"]
-codec = []
events = [
"std",
"radroots_event/serde",
"radroots_event_codec/json",
]
-nip17 = ["std", "codec", "nostr/nip44", "nostr/nip59"]
+nip17 = ["events", "nostr/nip44", "nostr/nip59"]
signing = [
"events",
"dep:radroots_signing",
@@ -80,15 +79,15 @@ required-features = ["events"]
[[test]]
name = "nip10_reply_profile"
-required-features = ["codec", "events"]
+required-features = ["events"]
[[test]]
name = "nip09_deletion_request_profile"
-required-features = ["codec", "events"]
+required-features = ["events"]
[[test]]
name = "nip22_comment_profile"
-required-features = ["codec", "events"]
+required-features = ["events"]
[[test]]
name = "blossom_conformance"
diff --git a/crates/nostr/README.md b/crates/nostr/README.md
@@ -111,7 +111,7 @@ message state.
`radroots_event`, `radroots_event_codec`, or versioned `radroots_protocol`
contracts.
- Explicit Nostr boundary aliases use the upstream NIP-01 JSON representation.
-- `RadrootsNostrExternalSigningRequest` serializes only as the standard
+- `event::ExternalSigningRequest` serializes only as the standard
unsigned Nostr event after reserved-kind and authoring-policy validation.
- Returned externally signed events are accepted only when author, canonical
event ID, and the complete NIP-01 signature verify against the request.
@@ -148,9 +148,7 @@ authority, upload completion, referenced-event existence, or relay trust.
| `blossom` | no | Adds BUD-11 signed HTTP authorization value creation and verification; no HTTP client or endpoint operation. |
Features are additive. `--no-default-features` provides the portable
-`no_std + alloc` conversion core. The manifest's `codec` feature is a
-non-release compatibility switch used by older focused adapters; it is not in
-the supported public feature vocabulary.
+`no_std + alloc` conversion core.
## Intended consumers
diff --git a/crates/nostr/src/blossom.rs b/crates/nostr/src/blossom.rs
@@ -33,14 +33,14 @@ const PERMISSIVE_URL_SAFE_NO_PAD: GeneralPurpose = GeneralPurpose::new(
/// A kind-24242 event minted from a strict authored Blossom upload claim.
#[derive(Clone, PartialEq, Eq)]
-pub struct RadrootsNostrSignedBlossomAuthorization {
+pub struct SignedAuthorization {
event: RadrootsNostrEvent,
}
-impl fmt::Debug for RadrootsNostrSignedBlossomAuthorization {
+impl fmt::Debug for SignedAuthorization {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
- .debug_struct("RadrootsNostrSignedBlossomAuthorization")
+ .debug_struct("SignedAuthorization")
.field("event_id", &self.event.id)
.field("author", &self.event.pubkey)
.field("created_at", &self.event.created_at)
@@ -48,7 +48,7 @@ impl fmt::Debug for RadrootsNostrSignedBlossomAuthorization {
}
}
-impl RadrootsNostrSignedBlossomAuthorization {
+impl SignedAuthorization {
pub fn event_id(&self) -> RadrootsNostrEventId {
self.event.id
}
@@ -64,9 +64,9 @@ impl RadrootsNostrSignedBlossomAuthorization {
/// A canonical BUD-11 HTTP `Authorization` value.
#[derive(Clone, PartialEq, Eq)]
-pub struct RadrootsNostrBlossomAuthorizationHeader(String);
+pub struct AuthorizationHeader(String);
-impl RadrootsNostrBlossomAuthorizationHeader {
+impl AuthorizationHeader {
pub fn as_str(&self) -> &str {
&self.0
}
@@ -76,16 +76,16 @@ impl RadrootsNostrBlossomAuthorizationHeader {
}
}
-impl fmt::Debug for RadrootsNostrBlossomAuthorizationHeader {
+impl fmt::Debug for AuthorizationHeader {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
- .debug_tuple("RadrootsNostrBlossomAuthorizationHeader")
+ .debug_tuple("AuthorizationHeader")
.field(&"[REDACTED]")
.finish()
}
}
-impl AsRef<str> for RadrootsNostrBlossomAuthorizationHeader {
+impl AsRef<str> for AuthorizationHeader {
fn as_ref(&self) -> &str {
self.as_str()
}
@@ -93,15 +93,15 @@ impl AsRef<str> for RadrootsNostrBlossomAuthorizationHeader {
/// A signature-verified BUD-11 event whose pure claim policy also passed.
#[derive(Clone, PartialEq, Eq)]
-pub struct RadrootsNostrVerifiedBlossomAuthorization {
+pub struct VerifiedAuthorization {
event: RadrootsNostrEvent,
claim: ValidatedAuthorizationClaim,
}
-impl fmt::Debug for RadrootsNostrVerifiedBlossomAuthorization {
+impl fmt::Debug for VerifiedAuthorization {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
- .debug_struct("RadrootsNostrVerifiedBlossomAuthorization")
+ .debug_struct("VerifiedAuthorization")
.field("event_id", &self.event.id)
.field("author", &self.event.pubkey)
.field("created_at", &self.event.created_at)
@@ -109,7 +109,7 @@ impl fmt::Debug for RadrootsNostrVerifiedBlossomAuthorization {
}
}
-impl RadrootsNostrVerifiedBlossomAuthorization {
+impl VerifiedAuthorization {
pub fn event_id(&self) -> RadrootsNostrEventId {
self.event.id
}
@@ -130,7 +130,7 @@ impl RadrootsNostrVerifiedBlossomAuthorization {
/// Failures at the signed Blossom HTTP authorization boundary.
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
-pub enum RadrootsNostrBlossomError {
+pub enum AuthorizationError {
InvalidHeaderWhitespace,
InvalidHeaderScheme,
EmptyHeaderPayload,
@@ -146,7 +146,7 @@ pub enum RadrootsNostrBlossomError {
BlossomClaim(Error),
}
-impl RadrootsNostrBlossomError {
+impl AuthorizationError {
pub const fn code(&self) -> &'static str {
match self {
Self::InvalidHeaderWhitespace => "invalid_header_whitespace",
@@ -173,7 +173,7 @@ impl RadrootsNostrBlossomError {
}
}
-impl fmt::Display for RadrootsNostrBlossomError {
+impl fmt::Display for AuthorizationError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidHeaderWhitespace => {
@@ -214,19 +214,19 @@ impl fmt::Display for RadrootsNostrBlossomError {
}
}
-impl std::error::Error for RadrootsNostrBlossomError {}
+impl std::error::Error for AuthorizationError {}
-impl From<Error> for RadrootsNostrBlossomError {
+impl From<Error> for AuthorizationError {
fn from(error: Error) -> Self {
Self::BlossomClaim(error)
}
}
/// Sign a direct kind-24242 event from a strict authored BUD-11 upload claim.
-pub fn radroots_nostr_sign_blossom_authorization(
+pub fn sign_authorization(
keys: &RadrootsNostrKeys,
claim: &AuthoredUploadClaim,
-) -> Result<RadrootsNostrSignedBlossomAuthorization, RadrootsNostrBlossomError> {
+) -> Result<SignedAuthorization, AuthorizationError> {
let wire = claim.wire_parts();
let tags = wire
.tags()
@@ -254,37 +254,35 @@ pub fn radroots_nostr_sign_blossom_authorization(
fn finish_signed_event<E>(
result: Result<RadrootsNostrEvent, E>,
-) -> Result<RadrootsNostrSignedBlossomAuthorization, RadrootsNostrBlossomError> {
+) -> Result<SignedAuthorization, AuthorizationError> {
result
- .map(|event| RadrootsNostrSignedBlossomAuthorization { event })
- .map_err(|_| RadrootsNostrBlossomError::EventSigning)
+ .map(|event| SignedAuthorization { event })
+ .map_err(|_| AuthorizationError::EventSigning)
}
/// Encode a signed BUD-11 event as a canonical `Nostr` authorization value.
-pub fn radroots_nostr_encode_blossom_authorization_header(
- authorization: &RadrootsNostrSignedBlossomAuthorization,
-) -> RadrootsNostrBlossomAuthorizationHeader {
+pub fn encode_authorization_header(authorization: &SignedAuthorization) -> AuthorizationHeader {
// `nostr::Event` contains no fallible serializer fields or non-string map keys.
let json = serde_json::to_vec(&authorization.event)
.expect("Nostr event JSON serialization is infallible");
let payload = URL_SAFE_NO_PAD.encode(json);
- RadrootsNostrBlossomAuthorizationHeader(format!("{AUTHORIZATION_SCHEME}{payload}"))
+ AuthorizationHeader(format!("{AUTHORIZATION_SCHEME}{payload}"))
}
/// Decode, authenticate, parse, and validate a BUD-11 authorization value.
-pub fn radroots_nostr_decode_verify_blossom_authorization_header(
+pub fn decode_verify_authorization_header(
header: &str,
validation: &AuthorizationValidation,
-) -> Result<RadrootsNostrVerifiedBlossomAuthorization, RadrootsNostrBlossomError> {
+) -> Result<VerifiedAuthorization, AuthorizationError> {
if header.trim_start() != header {
- return Err(RadrootsNostrBlossomError::InvalidHeaderWhitespace);
+ return Err(AuthorizationError::InvalidHeaderWhitespace);
}
let bytes = header.as_bytes();
let Some(first_space) = bytes.iter().position(|byte| *byte == b' ') else {
- return Err(RadrootsNostrBlossomError::InvalidHeaderScheme);
+ return Err(AuthorizationError::InvalidHeaderScheme);
};
if !bytes[..first_space].eq_ignore_ascii_case(b"Nostr") {
- return Err(RadrootsNostrBlossomError::InvalidHeaderScheme);
+ return Err(AuthorizationError::InvalidHeaderScheme);
}
let payload_start = bytes[first_space..]
.iter()
@@ -292,30 +290,29 @@ pub fn radroots_nostr_decode_verify_blossom_authorization_header(
.map_or(bytes.len(), |offset| first_space + offset);
let payload = &header[payload_start..];
if payload.is_empty() {
- return Err(RadrootsNostrBlossomError::EmptyHeaderPayload);
+ return Err(AuthorizationError::EmptyHeaderPayload);
}
if payload.chars().any(char::is_whitespace) {
- return Err(RadrootsNostrBlossomError::InvalidHeaderWhitespace);
+ return Err(AuthorizationError::InvalidHeaderWhitespace);
}
if payload.contains('=') {
- return Err(RadrootsNostrBlossomError::HeaderPaddingForbidden);
+ return Err(AuthorizationError::HeaderPaddingForbidden);
}
let decoded = PERMISSIVE_URL_SAFE_NO_PAD
.decode(payload)
- .map_err(|_| RadrootsNostrBlossomError::InvalidHeaderBase64)?;
+ .map_err(|_| AuthorizationError::InvalidHeaderBase64)?;
if URL_SAFE_NO_PAD.encode(&decoded) != payload {
- return Err(RadrootsNostrBlossomError::NonCanonicalHeaderBase64);
+ return Err(AuthorizationError::NonCanonicalHeaderBase64);
}
- let json =
- String::from_utf8(decoded).map_err(|_| RadrootsNostrBlossomError::InvalidHeaderUtf8)?;
+ let json = String::from_utf8(decoded).map_err(|_| AuthorizationError::InvalidHeaderUtf8)?;
validate_raw_event_json(&json)?;
let event: RadrootsNostrEvent =
- serde_json::from_str(&json).map_err(|_| RadrootsNostrBlossomError::InvalidEventJson)?;
+ serde_json::from_str(&json).map_err(|_| AuthorizationError::InvalidEventJson)?;
if !event.verify_id() {
- return Err(RadrootsNostrBlossomError::InvalidEventId);
+ return Err(AuthorizationError::InvalidEventId);
}
if !event.verify_signature() {
- return Err(RadrootsNostrBlossomError::InvalidEventSignature);
+ return Err(AuthorizationError::InvalidEventSignature);
}
let tags: Vec<Vec<String>> = event
@@ -326,10 +323,10 @@ pub fn radroots_nostr_decode_verify_blossom_authorization_header(
let claim = AuthorizationClaim::parse(&event.content, event.created_at.as_secs(), &tags)?
.validate(validation)?;
- Ok(RadrootsNostrVerifiedBlossomAuthorization { event, claim })
+ Ok(VerifiedAuthorization { event, claim })
}
-fn validate_raw_event_json(json: &str) -> Result<(), RadrootsNostrBlossomError> {
+fn validate_raw_event_json(json: &str) -> Result<(), AuthorizationError> {
const EVENT_FIELDS: [&str; 7] = [
"id",
"pubkey",
@@ -341,22 +338,22 @@ fn validate_raw_event_json(json: &str) -> Result<(), RadrootsNostrBlossomError>
];
let value: serde_json::Value =
- serde_json::from_str(json).map_err(|_| RadrootsNostrBlossomError::InvalidEventJson)?;
+ serde_json::from_str(json).map_err(|_| AuthorizationError::InvalidEventJson)?;
let object = value
.as_object()
- .ok_or(RadrootsNostrBlossomError::InvalidEventJson)?;
+ .ok_or(AuthorizationError::InvalidEventJson)?;
if object.len() != EVENT_FIELDS.len()
|| !EVENT_FIELDS.iter().all(|field| object.contains_key(*field))
{
- return Err(RadrootsNostrBlossomError::InvalidEventJson);
+ return Err(AuthorizationError::InvalidEventJson);
}
let actual_kind = object
.get("kind")
.and_then(serde_json::Value::as_u64)
- .ok_or(RadrootsNostrBlossomError::InvalidEventJson)?;
+ .ok_or(AuthorizationError::InvalidEventJson)?;
if actual_kind != u64::from(RADROOTS_BLOSSOM_AUTHORIZATION_EVENT_KIND) {
- return Err(RadrootsNostrBlossomError::InvalidEventKind {
+ return Err(AuthorizationError::InvalidEventKind {
actual: actual_kind,
});
}
@@ -370,6 +367,6 @@ mod tests {
#[test]
fn blossom_signing_failure_maps_to_typed_adapter_error() {
let result = finish_signed_event(Err::<RadrootsNostrEvent, ()>(()));
- assert_eq!(result, Err(RadrootsNostrBlossomError::EventSigning));
+ assert_eq!(result, Err(AuthorizationError::EventSigning));
}
}
diff --git a/crates/nostr/src/draft_signing.rs b/crates/nostr/src/draft_signing.rs
@@ -5,27 +5,27 @@
#![forbid(unsafe_code)]
-use crate::error::RadrootsNostrError;
-use crate::events::radroots_nostr_build_event_unchecked;
+use crate::error::Error;
+use crate::events::build_event_unchecked;
use crate::types::{RadrootsNostrKeys, RadrootsNostrTimestamp};
use nostr::JsonUtil;
use radroots_event::draft::{EventDraft, SignedEvent};
use radroots_event::wire::Nip01EventWire;
-pub fn radroots_nostr_sign_frozen_draft(
+pub fn sign_frozen_draft(
keys: &RadrootsNostrKeys,
draft: &EventDraft,
-) -> Result<SignedEvent, RadrootsNostrError> {
+) -> Result<SignedEvent, Error> {
draft.validate_for_signing()?;
let actual_pubkey = keys.public_key().to_hex();
if actual_pubkey != draft.expected_pubkey().to_hex() {
- return Err(RadrootsNostrError::FrozenDraftPubkeyMismatch {
+ return Err(Error::FrozenDraftPubkeyMismatch {
expected_pubkey: draft.expected_pubkey().to_hex().to_owned(),
actual_pubkey,
});
}
- let event = radroots_nostr_build_event_unchecked(
+ let event = build_event_unchecked(
draft.kind_u32(),
draft.content().to_owned(),
draft.tags_as_vec(),
@@ -35,7 +35,7 @@ pub fn radroots_nostr_sign_frozen_draft(
let actual_event_id = event.id.to_hex();
let expected_event_id = draft.expected_event_id_hex();
if actual_event_id != expected_event_id {
- return Err(RadrootsNostrError::FrozenDraftEventIdMismatch {
+ return Err(Error::FrozenDraftEventIdMismatch {
expected_event_id,
actual_event_id,
});
@@ -48,16 +48,17 @@ pub fn radroots_nostr_sign_frozen_draft(
#[cfg(test)]
mod tests {
- use super::radroots_nostr_sign_frozen_draft;
- use crate::error::RadrootsNostrError;
+ use super::sign_frozen_draft;
+ use crate::error::Error;
use crate::test_fixtures::{FIXTURE_ALICE, FIXTURE_BOB};
- use crate::types::{RadrootsNostrKeys, RadrootsNostrSecretKey};
+ use crate::types::RadrootsNostrKeys;
use nostr::JsonUtil;
+ use nostr::SecretKey;
use radroots_event::draft::EventDraft;
use radroots_event::envelope::kind::KIND_GEOCHAT;
fn fixture_keys(secret_key_hex: &str) -> RadrootsNostrKeys {
- let secret_key = RadrootsNostrSecretKey::from_hex(secret_key_hex).expect("secret key");
+ let secret_key = SecretKey::from_hex(secret_key_hex).expect("secret key");
RadrootsNostrKeys::new(secret_key)
}
@@ -77,7 +78,7 @@ mod tests {
fn sign_frozen_draft_uses_fixed_created_at_and_expected_id() {
let keys = fixture_keys(FIXTURE_ALICE.secret_key_hex);
let draft = generic_draft(FIXTURE_ALICE.public_key_hex);
- let signed = radroots_nostr_sign_frozen_draft(&keys, &draft).expect("signed event");
+ let signed = sign_frozen_draft(&keys, &draft).expect("signed event");
assert_eq!(signed.id_str(), draft.expected_event_id_hex());
assert_eq!(signed.pubkey().to_hex(), draft.expected_pubkey().to_hex());
@@ -96,12 +97,9 @@ mod tests {
fn sign_frozen_draft_rejects_wrong_signer() {
let keys = fixture_keys(FIXTURE_BOB.secret_key_hex);
let draft = generic_draft(FIXTURE_ALICE.public_key_hex);
- let error = radroots_nostr_sign_frozen_draft(&keys, &draft).expect_err("wrong signer");
+ let error = sign_frozen_draft(&keys, &draft).expect_err("wrong signer");
- assert!(matches!(
- error,
- RadrootsNostrError::FrozenDraftPubkeyMismatch { .. }
- ));
+ assert!(matches!(error, Error::FrozenDraftPubkeyMismatch { .. }));
}
#[test]
diff --git a/crates/nostr/src/error.rs b/crates/nostr/src/error.rs
@@ -7,7 +7,7 @@ use alloc::{boxed::Box, string::String};
use thiserror::Error;
#[derive(Debug, Error)]
-pub enum RadrootsNostrError {
+pub enum Error {
#[error("invalid Nostr public key")]
InvalidPublicKey,
@@ -114,26 +114,26 @@ pub enum RadrootsNostrError {
FilterTagError(String),
}
-impl From<nostr::event::Error> for RadrootsNostrError {
+impl From<nostr::event::Error> for Error {
fn from(error: nostr::event::Error) -> Self {
Self::EventError(error)
}
}
-impl From<nostr::event::builder::Error> for RadrootsNostrError {
+impl From<nostr::event::builder::Error> for Error {
fn from(error: nostr::event::builder::Error) -> Self {
Self::EventBuildError(error)
}
}
-impl From<nostr::key::Error> for RadrootsNostrError {
+impl From<nostr::key::Error> for Error {
fn from(error: nostr::key::Error) -> Self {
Self::KeyError(error)
}
}
#[derive(Debug, Error)]
-pub enum RadrootsNostrTagsResolveError {
+pub enum ResolveError {
#[error("Missing public key 'p' tag in encrypted event: {0:?}")]
MissingPTag(Box<nostr::Event>),
diff --git a/crates/nostr/src/event.rs b/crates/nostr/src/event.rs
@@ -11,7 +11,47 @@ use radroots_event::id::Nip01Coordinate;
use crate::Error;
#[cfg(feature = "events")]
-pub use crate::types::{RadrootsNostrExternalSigningRequest, RadrootsNostrGenericEventBuilder};
+pub use crate::codec_adapters::{
+ to_job_feedback_index, to_job_feedback_metadata, to_job_request_index, to_job_request_metadata,
+ to_job_result_index, to_job_result_metadata,
+};
+#[cfg(feature = "events")]
+pub use crate::event_adapters::{to_post_event_metadata, to_profile_event_metadata};
+#[cfg(feature = "events")]
+pub use crate::event_verify::{
+ NostrSignatureVerifier as SignatureVerifier, Verification, verify_event as verify,
+ verify_event_id as verify_id,
+};
+#[cfg(feature = "events")]
+pub use crate::events::{
+ application_handler::{
+ ApplicationHandlerSpec, build_application_handler_event as build_application_handler,
+ metadata_has_fields,
+ },
+ comment::{Nip22CommentBuilder, build_nip22_comment_event as build_nip22_comment},
+ deletion::{
+ Nip09DeletionRequestBuilder,
+ build_nip09_deletion_request_event as build_nip09_deletion_request,
+ },
+ food_availability::{
+ FoodAvailabilityBuilder, build_food_availability_event as build_food_availability,
+ },
+ jobs::{
+ build_event_job_feedback as build_job_feedback, build_event_job_result as build_job_result,
+ },
+ metadata::{ProfileBuilder, build_profile_event as build_profile},
+ post::{
+ PostBuilder, build_ask_event as build_ask, build_photo_update_event as build_photo_update,
+ build_update_event as build_update, post_events_filter as post_filter,
+ },
+ reply::{Nip10ReplyBuilder, build_nip10_reply_event as build_nip10_reply},
+};
+#[cfg(feature = "events")]
+pub use crate::job_adapter::EventAdapter;
+#[cfg(feature = "events")]
+pub use crate::types::{ExternalSigningRequest, GenericBuilder};
+#[cfg(feature = "events")]
+pub use crate::util::{created_at_u32_saturating, event_created_at_u32_saturating};
/// Upstream Nostr coordinate used only at the explicit protocol boundary.
pub type Coordinate = nostr::nips::nip01::Coordinate;
@@ -27,9 +67,7 @@ pub type Metadata = nostr::Metadata;
pub type Timestamp = nostr::Timestamp;
#[cfg(feature = "events")]
-pub use crate::event_convert::{
- nostr_event_from_radroots, radroots_event_from_nostr, radroots_event_ptr_from_nostr,
-};
+pub use crate::event_convert::{from_nostr, pointer_from_nostr, to_nostr};
/// Converts a canonical Radroots NIP-01 coordinate to its Nostr value.
pub fn coordinate_to_nostr(coordinate: &Nip01Coordinate) -> Result<Coordinate, Error> {
diff --git a/crates/nostr/src/event_adapters.rs b/crates/nostr/src/event_adapters.rs
@@ -22,7 +22,7 @@ use crate::types::{RadrootsNostrEvent, RadrootsNostrMetadata};
/// Adapts an event through the compatibility-only legacy post projection.
///
/// This helper discards tags and does not establish product profile admission.
-/// Use `verify_and_admit_post_event` over `radroots_event_from_nostr` whenever
+/// Use `verify_and_admit_post_event` over `from_nostr` whenever
/// the caller needs root Update, PhotoUpdate, or Ask admission. Its explicit
/// thread-excluded outcome makes no Reply claim.
pub fn to_post_event_metadata(e: &RadrootsNostrEvent) -> RadrootsParsedData<LegacyPost> {
diff --git a/crates/nostr/src/event_convert.rs b/crates/nostr/src/event_convert.rs
@@ -1,15 +1,13 @@
#![forbid(unsafe_code)]
-use crate::error::RadrootsNostrError;
+use crate::error::Error;
use crate::types::RadrootsNostrEvent as RadrootsNostrRawEvent;
use radroots_event::{
envelope::EventEnvelope, envelope::EventEnvelopeError, envelope::EventEnvelopeParts,
tag::EventPtr,
};
-pub fn radroots_event_from_nostr(
- event: &RadrootsNostrRawEvent,
-) -> Result<EventEnvelope, EventEnvelopeError> {
+pub fn from_nostr(event: &RadrootsNostrRawEvent) -> Result<EventEnvelope, EventEnvelopeError> {
EventEnvelope::new(EventEnvelopeParts {
id: event.id.to_string(),
author: event.pubkey.to_string(),
@@ -25,25 +23,23 @@ pub fn radroots_event_from_nostr(
///
/// This adapter performs no network access and does not imply that the event's
/// identifier or signature has been verified.
-pub fn nostr_event_from_radroots(
- event: &EventEnvelope,
-) -> Result<RadrootsNostrRawEvent, RadrootsNostrError> {
- let kind = u16::try_from(event.kind_u32()).map_err(|_| RadrootsNostrError::KindOutOfRange {
+pub fn to_nostr(event: &EventEnvelope) -> Result<RadrootsNostrRawEvent, Error> {
+ let kind = u16::try_from(event.kind_u32()).map_err(|_| Error::KindOutOfRange {
kind: event.kind_u32(),
max: u16::MAX,
})?;
let id = nostr::EventId::from_slice(event.id().as_bytes())
- .map_err(|_| RadrootsNostrError::EventConversion { field: "id" })?;
+ .map_err(|_| Error::EventConversion { field: "id" })?;
let public_key = nostr::PublicKey::from_slice(event.author().as_bytes())
- .map_err(|_| RadrootsNostrError::EventConversion { field: "author" })?;
+ .map_err(|_| Error::EventConversion { field: "author" })?;
let signature = nostr::secp256k1::schnorr::Signature::from_slice(event.sig().as_bytes())
- .map_err(|_| RadrootsNostrError::EventConversion { field: "signature" })?;
+ .map_err(|_| Error::EventConversion { field: "signature" })?;
let tags = event
.tags_as_vec()
.into_iter()
.map(nostr::Tag::parse)
.collect::<Result<Vec<_>, _>>()
- .map_err(|_| RadrootsNostrError::EventConversion { field: "tags" })?;
+ .map_err(|_| Error::EventConversion { field: "tags" })?;
Ok(nostr::Event::new(
id,
@@ -56,7 +52,7 @@ pub fn nostr_event_from_radroots(
))
}
-pub fn radroots_event_ptr_from_nostr(event: &RadrootsNostrRawEvent) -> EventPtr {
+pub fn pointer_from_nostr(event: &RadrootsNostrRawEvent) -> EventPtr {
EventPtr {
id: event.id.to_string(),
relays: None,
@@ -66,22 +62,22 @@ pub fn radroots_event_ptr_from_nostr(event: &RadrootsNostrRawEvent) -> EventPtr
#[cfg(test)]
mod tests {
use super::*;
- use crate::events::radroots_nostr_build_event_unchecked;
+ use crate::events::build_event_unchecked;
use crate::test_fixtures::FIXTURE_ALICE;
- use crate::types::{RadrootsNostrKeys, RadrootsNostrSecretKey, RadrootsNostrTimestamp};
+ use crate::types::{RadrootsNostrKeys, RadrootsNostrTimestamp};
+ use nostr::SecretKey;
use radroots_event::{
envelope::EventEnvelopeParts,
wire::{DEFAULT_CONTENT_MAX_BYTES, DEFAULT_TAG_TOTAL_ELEMENT_MAX_COUNT},
};
fn fixture_keys() -> RadrootsNostrKeys {
- let secret_key =
- RadrootsNostrSecretKey::from_hex(FIXTURE_ALICE.secret_key_hex).expect("secret key");
+ let secret_key = SecretKey::from_hex(FIXTURE_ALICE.secret_key_hex).expect("secret key");
RadrootsNostrKeys::new(secret_key)
}
fn signed_event(content: String, tags: Vec<Vec<String>>) -> RadrootsNostrRawEvent {
- radroots_nostr_build_event_unchecked(1, content, tags)
+ build_event_unchecked(1, content, tags)
.expect("builder")
.custom_created_at(RadrootsNostrTimestamp::from_secs(1_700_000_000))
.sign_with_keys(&fixture_keys())
@@ -94,9 +90,9 @@ mod tests {
"harvest update".to_owned(),
vec![vec!["t".to_owned(), "soil".to_owned()]],
);
- let envelope = radroots_event_from_nostr(&original).expect("Radroots envelope");
+ let envelope = from_nostr(&original).expect("Radroots envelope");
- let converted = nostr_event_from_radroots(&envelope).expect("Nostr event");
+ let converted = to_nostr(&envelope).expect("Nostr event");
assert_eq!(converted, original);
}
@@ -104,7 +100,7 @@ mod tests {
#[test]
fn conversion_rejects_kind_outside_nostr_range() {
let original = signed_event(String::new(), Vec::new());
- let envelope = radroots_event_from_nostr(&original).expect("Radroots envelope");
+ let envelope = from_nostr(&original).expect("Radroots envelope");
let kind = u32::from(u16::MAX) + 1;
let widened = EventEnvelope::new(EventEnvelopeParts {
id: envelope.id_hex(),
@@ -118,8 +114,8 @@ mod tests {
.expect("wider Radroots kind");
assert!(matches!(
- nostr_event_from_radroots(&widened),
- Err(RadrootsNostrError::KindOutOfRange {
+ to_nostr(&widened),
+ Err(Error::KindOutOfRange {
kind: actual,
max: u16::MAX,
}) if actual == kind
@@ -132,7 +128,7 @@ mod tests {
let event = signed_event(content, Vec::new());
assert_eq!(
- radroots_event_from_nostr(&event),
+ from_nostr(&event),
Err(EventEnvelopeError::ContentTooLarge {
max: DEFAULT_CONTENT_MAX_BYTES,
actual: DEFAULT_CONTENT_MAX_BYTES + 1,
@@ -148,7 +144,7 @@ mod tests {
let event = signed_event(String::new(), vec![tag]);
assert_eq!(
- radroots_event_from_nostr(&event),
+ from_nostr(&event),
Err(EventEnvelopeError::TooManyTagElements {
max: DEFAULT_TAG_TOTAL_ELEMENT_MAX_COUNT,
actual: DEFAULT_TAG_TOTAL_ELEMENT_MAX_COUNT + 1,
diff --git a/crates/nostr/src/event_verify.rs b/crates/nostr/src/event_verify.rs
@@ -30,7 +30,7 @@ impl SignatureVerifier for NostrSignatureVerifier {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum RadrootsNostrEventVerification {
+pub enum Verification {
Verified,
IdVerified,
IdMismatch,
@@ -38,20 +38,20 @@ pub enum RadrootsNostrEventVerification {
MalformedEnvelope,
}
-pub fn radroots_nostr_verify_event(event: &EventEnvelope) -> RadrootsNostrEventVerification {
+pub fn verify_event(event: &EventEnvelope) -> Verification {
let result = validate_nostr_kind(event)
.and_then(|()| verify::id(RawEvent::new(event.clone())))
.and_then(|event| verify::signature(event, &NostrSignatureVerifier));
match result {
- Ok(_) => RadrootsNostrEventVerification::Verified,
+ Ok(_) => Verification::Verified,
Err(error) => verification_error_status(&error),
}
}
-pub fn radroots_nostr_verify_event_id(event: &EventEnvelope) -> RadrootsNostrEventVerification {
+pub fn verify_event_id(event: &EventEnvelope) -> Verification {
let result = validate_nostr_kind(event).and_then(|()| verify::id(RawEvent::new(event.clone())));
match result {
- Ok(_) => RadrootsNostrEventVerification::IdVerified,
+ Ok(_) => Verification::IdVerified,
Err(error) => verification_error_status(&error),
}
}
@@ -62,37 +62,37 @@ fn validate_nostr_kind(event: &EventEnvelope) -> Result<(), VerificationError> {
.map_err(|_| VerificationError::MalformedEnvelope)
}
-fn verification_error_status(error: &VerificationError) -> RadrootsNostrEventVerification {
+fn verification_error_status(error: &VerificationError) -> Verification {
match error {
- VerificationError::IdMismatch { .. } => RadrootsNostrEventVerification::IdMismatch,
- VerificationError::SignatureInvalid => RadrootsNostrEventVerification::SignatureInvalid,
+ VerificationError::IdMismatch { .. } => Verification::IdMismatch,
+ VerificationError::SignatureInvalid => Verification::SignatureInvalid,
VerificationError::MalformedEnvelope | VerificationError::ContractValidation(_) => {
- RadrootsNostrEventVerification::MalformedEnvelope
+ Verification::MalformedEnvelope
}
- _ => RadrootsNostrEventVerification::MalformedEnvelope,
+ _ => Verification::MalformedEnvelope,
}
}
#[cfg(test)]
mod tests {
use super::*;
- use crate::event_convert::radroots_event_from_nostr;
- use crate::events::radroots_nostr_build_event_unchecked;
+ use crate::event_convert::from_nostr;
+ use crate::events::build_event_unchecked;
use crate::test_fixtures::FIXTURE_ALICE;
- use crate::types::{RadrootsNostrKeys, RadrootsNostrSecretKey, RadrootsNostrTimestamp};
+ use crate::types::{RadrootsNostrKeys, RadrootsNostrTimestamp};
+ use nostr::SecretKey;
use radroots_event::{
envelope::EventEnvelopeParts, envelope::kind::KIND_POST,
wire::compute_canonical_nip01_event_id,
};
fn fixture_keys() -> RadrootsNostrKeys {
- let secret_key =
- RadrootsNostrSecretKey::from_hex(FIXTURE_ALICE.secret_key_hex).expect("secret key");
+ let secret_key = SecretKey::from_hex(FIXTURE_ALICE.secret_key_hex).expect("secret key");
RadrootsNostrKeys::new(secret_key)
}
fn signed_event() -> EventEnvelope {
- let raw_event = radroots_nostr_build_event_unchecked(
+ let raw_event = build_event_unchecked(
KIND_POST,
"hello",
vec![vec!["t".to_owned(), "soil".to_owned()]],
@@ -101,7 +101,7 @@ mod tests {
.custom_created_at(RadrootsNostrTimestamp::from_secs(1_700_000_000))
.sign_with_keys(&fixture_keys())
.expect("signed event");
- radroots_event_from_nostr(&raw_event).expect("Radroots event envelope")
+ from_nostr(&raw_event).expect("Radroots event envelope")
}
fn envelope_with(
@@ -126,14 +126,8 @@ mod tests {
fn verifies_signed_event_id_and_signature() {
let event = signed_event();
- assert_eq!(
- radroots_nostr_verify_event(&event),
- RadrootsNostrEventVerification::Verified
- );
- assert_eq!(
- radroots_nostr_verify_event_id(&event),
- RadrootsNostrEventVerification::IdVerified
- );
+ assert_eq!(verify_event(&event), Verification::Verified);
+ assert_eq!(verify_event_id(&event), Verification::IdVerified);
}
#[test]
@@ -146,10 +140,7 @@ mod tests {
original.signature_hex(),
);
- assert_eq!(
- radroots_nostr_verify_event(&event),
- RadrootsNostrEventVerification::IdMismatch
- );
+ assert_eq!(verify_event(&event), Verification::IdMismatch);
}
#[test]
@@ -165,10 +156,7 @@ mod tests {
sig,
);
- assert_eq!(
- radroots_nostr_verify_event(&event),
- RadrootsNostrEventVerification::SignatureInvalid
- );
+ assert_eq!(verify_event(&event), Verification::SignatureInvalid);
}
#[test]
@@ -181,14 +169,8 @@ mod tests {
original.signature_hex(),
);
- assert_eq!(
- radroots_nostr_verify_event(&event),
- RadrootsNostrEventVerification::MalformedEnvelope
- );
- assert_eq!(
- radroots_nostr_verify_event_id(&event),
- RadrootsNostrEventVerification::MalformedEnvelope
- );
+ assert_eq!(verify_event(&event), Verification::MalformedEnvelope);
+ assert_eq!(verify_event_id(&event), Verification::MalformedEnvelope);
}
#[test]
@@ -215,13 +197,7 @@ mod tests {
})
.expect("envelope");
- assert_eq!(
- radroots_nostr_verify_event(&event),
- RadrootsNostrEventVerification::MalformedEnvelope
- );
- assert_eq!(
- radroots_nostr_verify_event_id(&event),
- RadrootsNostrEventVerification::MalformedEnvelope
- );
+ assert_eq!(verify_event(&event), Verification::MalformedEnvelope);
+ assert_eq!(verify_event_id(&event), Verification::MalformedEnvelope);
}
}
diff --git a/crates/nostr/src/events/application_handler.rs b/crates/nostr/src/events/application_handler.rs
@@ -6,22 +6,22 @@ extern crate alloc;
use alloc::{string::String, vec::Vec};
-use crate::error::RadrootsNostrError;
-use crate::events::radroots_nostr_build_event_unchecked;
-use crate::types::{RadrootsNostrGenericEventBuilder, RadrootsNostrMetadata};
+use crate::error::Error;
+use crate::events::build_event_unchecked;
+use crate::types::{GenericBuilder, RadrootsNostrMetadata};
use radroots_event::envelope::kind::KIND_APPLICATION_HANDLER;
#[derive(Debug, Clone)]
-pub struct RadrootsNostrApplicationHandlerSpec {
- pub kinds: Vec<u32>,
- pub identifier: Option<String>,
- pub metadata: Option<RadrootsNostrMetadata>,
- pub extra_tags: Vec<Vec<String>>,
- pub relays: Vec<String>,
- pub nostrconnect_url: Option<String>,
+pub struct ApplicationHandlerSpec {
+ kinds: Vec<u32>,
+ identifier: Option<String>,
+ metadata: Option<RadrootsNostrMetadata>,
+ extra_tags: Vec<Vec<String>>,
+ relays: Vec<String>,
+ nostrconnect_url: Option<String>,
}
-impl RadrootsNostrApplicationHandlerSpec {
+impl ApplicationHandlerSpec {
pub fn new(kinds: Vec<u32>) -> Self {
Self {
kinds,
@@ -32,13 +32,67 @@ impl RadrootsNostrApplicationHandlerSpec {
nostrconnect_url: None,
}
}
+
+ #[must_use]
+ pub fn with_identifier(mut self, identifier: impl Into<String>) -> Self {
+ self.identifier = Some(identifier.into());
+ self
+ }
+
+ #[must_use]
+ pub fn with_metadata(mut self, metadata: RadrootsNostrMetadata) -> Self {
+ self.metadata = Some(metadata);
+ self
+ }
+
+ #[must_use]
+ pub fn with_extra_tags(mut self, extra_tags: Vec<Vec<String>>) -> Self {
+ self.extra_tags = extra_tags;
+ self
+ }
+
+ #[must_use]
+ pub fn with_relays(mut self, relays: Vec<String>) -> Self {
+ self.relays = relays;
+ self
+ }
+
+ #[must_use]
+ pub fn with_nostr_connect_url(mut self, url: impl Into<String>) -> Self {
+ self.nostrconnect_url = Some(url.into());
+ self
+ }
+
+ pub fn kinds(&self) -> &[u32] {
+ &self.kinds
+ }
+
+ pub fn identifier(&self) -> Option<&str> {
+ self.identifier.as_deref()
+ }
+
+ pub fn metadata(&self) -> Option<&RadrootsNostrMetadata> {
+ self.metadata.as_ref()
+ }
+
+ pub fn extra_tags(&self) -> &[Vec<String>] {
+ &self.extra_tags
+ }
+
+ pub fn relays(&self) -> &[String] {
+ &self.relays
+ }
+
+ pub fn nostr_connect_url(&self) -> Option<&str> {
+ self.nostrconnect_url.as_deref()
+ }
}
-pub fn radroots_nostr_build_application_handler_event(
- spec: &RadrootsNostrApplicationHandlerSpec,
-) -> Result<RadrootsNostrGenericEventBuilder, RadrootsNostrError> {
+pub fn build_application_handler_event(
+ spec: &ApplicationHandlerSpec,
+) -> Result<GenericBuilder, Error> {
if spec.kinds.is_empty() {
- return Err(RadrootsNostrError::FilterTagError(
+ return Err(Error::FilterTagError(
"application handler kinds are empty".to_string(),
));
}
@@ -50,7 +104,7 @@ pub fn radroots_nostr_build_application_handler_event(
let mut content = String::new();
if let Some(md) = spec.metadata.as_ref()
- && radroots_nostr_metadata_has_fields(md)
+ && metadata_has_fields(md)
{
content = serde_json::to_string(md).unwrap_or_default();
}
@@ -80,11 +134,11 @@ pub fn radroots_nostr_build_application_handler_event(
tags.push(tag.clone());
}
- let builder = radroots_nostr_build_event_unchecked(KIND_APPLICATION_HANDLER, content, tags)?;
- Ok(RadrootsNostrGenericEventBuilder::from_unchecked(builder))
+ let builder = build_event_unchecked(KIND_APPLICATION_HANDLER, content, tags)?;
+ Ok(GenericBuilder::from_unchecked(builder))
}
-pub fn radroots_nostr_metadata_has_fields(md: &RadrootsNostrMetadata) -> bool {
+pub fn metadata_has_fields(md: &RadrootsNostrMetadata) -> bool {
md.name.is_some()
|| md.display_name.is_some()
|| md.about.is_some()
@@ -99,14 +153,12 @@ pub fn radroots_nostr_metadata_has_fields(md: &RadrootsNostrMetadata) -> bool {
#[cfg(test)]
mod tests {
- use super::radroots_nostr_metadata_has_fields;
+ use super::metadata_has_fields;
use crate::types::RadrootsNostrMetadata;
#[test]
fn metadata_has_fields_false_when_empty() {
- assert!(!radroots_nostr_metadata_has_fields(
- &RadrootsNostrMetadata::default()
- ));
+ assert!(!metadata_has_fields(&RadrootsNostrMetadata::default()));
}
#[test]
@@ -115,6 +167,6 @@ mod tests {
about: Some("ready".to_string()),
..Default::default()
};
- assert!(radroots_nostr_metadata_has_fields(&metadata));
+ assert!(metadata_has_fields(&metadata));
}
}
diff --git a/crates/nostr/src/events/comment.rs b/crates/nostr/src/events/comment.rs
@@ -1,7 +1,7 @@
//! Sealed authoring for strict NIP-22 Comment events.
use crate::{
- error::RadrootsNostrError,
+ error::Error,
types::{
RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrKeys,
RadrootsNostrTimestamp,
@@ -15,43 +15,37 @@ use radroots_event_codec::encode::comment::authored_nip22_comment_to_wire_parts;
/// The wrapper exposes no raw builder conversion or tag/content mutation.
///
/// ```compile_fail
-/// use radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder;
+/// use radroots_nostr::event::Nip22CommentBuilder;
///
-/// fn expose_raw_builder(builder: RadrootsNostrNip22CommentEventBuilder) {
+/// fn expose_raw_builder(builder: Nip22CommentBuilder) {
/// let _: nostr::EventBuilder = builder.into();
/// }
/// ```
#[must_use = "NIP-22 Comment builders must be signed or published"]
-pub struct RadrootsNostrNip22CommentEventBuilder {
+pub struct Nip22CommentBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
-impl RadrootsNostrNip22CommentEventBuilder {
+impl Nip22CommentBuilder {
pub fn custom_created_at(mut self, created_at: RadrootsNostrTimestamp) -> Self {
self.inner = self.inner.custom_created_at(created_at);
self
}
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
-pub fn radroots_nostr_build_nip22_comment_event(
+pub fn build_nip22_comment_event(
comment: &AuthoredNip22Comment,
-) -> Result<RadrootsNostrNip22CommentEventBuilder, RadrootsNostrError> {
+) -> Result<Nip22CommentBuilder, Error> {
builder_from_wire_parts(authored_nip22_comment_to_wire_parts(comment))
}
-fn builder_from_wire_parts(
- parts: Nip01EventWireParts,
-) -> Result<RadrootsNostrNip22CommentEventBuilder, RadrootsNostrError> {
- let inner =
- crate::events::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?;
- Ok(RadrootsNostrNip22CommentEventBuilder { inner })
+fn builder_from_wire_parts(parts: Nip01EventWireParts) -> Result<Nip22CommentBuilder, Error> {
+ let inner = crate::events::build_event_unchecked(parts.kind, parts.content, parts.tags)?;
+ Ok(Nip22CommentBuilder { inner })
}
#[cfg(test)]
@@ -74,7 +68,7 @@ mod tests {
.expect("root");
let comment = AuthoredNip22Comment::top_level_event("Comment", root).expect("comment");
let keys = RadrootsNostrKeys::generate();
- let event = radroots_nostr_build_nip22_comment_event(&comment)
+ let event = build_nip22_comment_event(&comment)
.expect("builder")
.custom_created_at(RadrootsNostrTimestamp::from_secs(1_800_000_000))
.sign_with_keys(&keys)
diff --git a/crates/nostr/src/events/deletion.rs b/crates/nostr/src/events/deletion.rs
@@ -1,7 +1,7 @@
//! Sealed authoring for validated NIP-09 deletion requests.
use crate::{
- error::RadrootsNostrError,
+ error::Error,
types::{
RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrKeys,
RadrootsNostrTimestamp,
@@ -17,53 +17,48 @@ use radroots_event_codec::encode::deletion::authored_nip09_deletion_request_to_w
/// effect.
///
/// ```compile_fail
-/// use radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder;
+/// use radroots_nostr::event::Nip09DeletionRequestBuilder;
///
-/// fn expose_raw_builder(builder: RadrootsNostrNip09DeletionRequestEventBuilder) {
+/// fn expose_raw_builder(builder: Nip09DeletionRequestBuilder) {
/// let _: nostr::EventBuilder = builder.into();
/// }
/// ```
///
/// ```compile_fail
-/// use radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder;
-/// use radroots_nostr::tag::Tag as RadrootsNostrTag;
+/// use radroots_nostr::{event::Nip09DeletionRequestBuilder, tag::Tag};
///
/// fn mutate_validated_tags(
-/// builder: RadrootsNostrNip09DeletionRequestEventBuilder,
-/// tag: RadrootsNostrTag,
+/// builder: Nip09DeletionRequestBuilder,
+/// tag: Tag,
/// ) {
/// let _ = builder.tag(tag);
/// }
/// ```
#[must_use = "NIP-09 deletion request builders must be signed or published"]
-pub struct RadrootsNostrNip09DeletionRequestEventBuilder {
+pub struct Nip09DeletionRequestBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
-impl RadrootsNostrNip09DeletionRequestEventBuilder {
+impl Nip09DeletionRequestBuilder {
pub fn custom_created_at(mut self, created_at: RadrootsNostrTimestamp) -> Self {
self.inner = self.inner.custom_created_at(created_at);
self
}
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
-pub fn radroots_nostr_build_nip09_deletion_request_event(
+pub fn build_nip09_deletion_request_event(
request: &AuthoredNip09DeletionRequest,
-) -> Result<RadrootsNostrNip09DeletionRequestEventBuilder, RadrootsNostrError> {
+) -> Result<Nip09DeletionRequestBuilder, Error> {
builder_from_wire_parts(authored_nip09_deletion_request_to_wire_parts(request))
}
fn builder_from_wire_parts(
parts: Nip01EventWireParts,
-) -> Result<RadrootsNostrNip09DeletionRequestEventBuilder, RadrootsNostrError> {
- let inner =
- crate::events::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?;
- Ok(RadrootsNostrNip09DeletionRequestEventBuilder { inner })
+) -> Result<Nip09DeletionRequestBuilder, Error> {
+ let inner = crate::events::build_event_unchecked(parts.kind, parts.content, parts.tags)?;
+ Ok(Nip09DeletionRequestBuilder { inner })
}
diff --git a/crates/nostr/src/events/food_availability.rs b/crates/nostr/src/events/food_availability.rs
@@ -1,7 +1,7 @@
//! Sealed authoring for focused Radroots FoodAvailability events.
use crate::{
- error::RadrootsNostrError,
+ error::Error,
types::{
RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrKeys,
RadrootsNostrTimestamp,
@@ -18,34 +18,30 @@ use radroots_event_codec::encode::food_availability::authored_food_availability_
/// caller must prove successful BUD-02 upload before signing or publication.
///
/// ```compile_fail
-/// use radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder;
-/// use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
+/// use radroots_nostr::event::{FoodAvailabilityBuilder, Timestamp};
///
-/// fn replace_validated_timestamp(builder: RadrootsNostrFoodAvailabilityEventBuilder) {
-/// let _ = builder.custom_created_at(RadrootsNostrTimestamp::from_secs(1));
+/// fn replace_validated_timestamp(builder: FoodAvailabilityBuilder) {
+/// let _ = builder.custom_created_at(Timestamp::from_secs(1));
/// }
/// ```
///
/// ```compile_fail
-/// use radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder;
+/// use radroots_nostr::event::FoodAvailabilityBuilder;
///
-/// fn expose_raw_builder(builder: RadrootsNostrFoodAvailabilityEventBuilder) {
+/// fn expose_raw_builder(builder: FoodAvailabilityBuilder) {
/// let _: nostr::EventBuilder = builder.into();
/// }
/// ```
#[must_use = "FoodAvailability event builders must be signed or published"]
-pub struct RadrootsNostrFoodAvailabilityEventBuilder {
+pub struct FoodAvailabilityBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
-impl RadrootsNostrFoodAvailabilityEventBuilder {
+impl FoodAvailabilityBuilder {
/// Signs the validated event directly with local keys.
///
/// Media-bearing callers must prove successful BUD-02 upload first.
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
@@ -53,12 +49,12 @@ impl RadrootsNostrFoodAvailabilityEventBuilder {
/// Builds a sealed Nostr builder from strict FoodAvailability details.
///
/// This validates media descriptors but does not attest BUD-02 upload.
-pub fn radroots_nostr_build_food_availability_event(
+pub fn build_food_availability_event(
details: &FoodAvailabilityDetails,
created_at: RadrootsNostrTimestamp,
-) -> Result<RadrootsNostrFoodAvailabilityEventBuilder, RadrootsNostrError> {
+) -> Result<FoodAvailabilityBuilder, Error> {
let parts = authored_food_availability_to_wire_parts(details, created_at.as_secs())?;
- let inner = super::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?
+ let inner = super::build_event_unchecked(parts.kind, parts.content, parts.tags)?
.custom_created_at(created_at);
- Ok(RadrootsNostrFoodAvailabilityEventBuilder { inner })
+ Ok(FoodAvailabilityBuilder { inner })
}
diff --git a/crates/nostr/src/events/jobs.rs b/crates/nostr/src/events/jobs.rs
@@ -4,19 +4,18 @@ use alloc::{string::String, vec::Vec};
use nostr::nips::nip90::{DataVendingMachineStatus, JobFeedbackData};
-use crate::error::RadrootsNostrError;
+use crate::error::Error;
use crate::types::{
- RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrGenericEventBuilder,
- RadrootsNostrTag,
+ GenericBuilder, RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrTag,
};
-pub fn radroots_nostr_build_event_job_result(
+pub fn build_event_job_result(
job_request: &RadrootsNostrEvent,
payload: impl Into<String>,
millisats: u64,
bolt11: Option<String>,
tags: Option<Vec<RadrootsNostrTag>>,
-) -> Result<RadrootsNostrGenericEventBuilder, RadrootsNostrError> {
+) -> Result<GenericBuilder, Error> {
let builder = RadrootsNostrEventBuilderUnchecked::job_result(
job_request.clone(),
payload,
@@ -25,15 +24,15 @@ pub fn radroots_nostr_build_event_job_result(
)?
.tags(tags.unwrap_or_default())
.allow_self_tagging();
- Ok(RadrootsNostrGenericEventBuilder::from_unchecked(builder))
+ Ok(GenericBuilder::from_unchecked(builder))
}
-pub fn radroots_nostr_build_event_job_feedback(
+pub fn build_event_job_feedback(
job_request: &RadrootsNostrEvent,
status: &str,
extra_info: Option<String>,
tags: Option<Vec<RadrootsNostrTag>>,
-) -> Result<RadrootsNostrGenericEventBuilder, RadrootsNostrError> {
+) -> Result<GenericBuilder, Error> {
let status = status
.parse::<DataVendingMachineStatus>()
.unwrap_or(DataVendingMachineStatus::Error);
@@ -42,5 +41,5 @@ pub fn radroots_nostr_build_event_job_feedback(
let builder = RadrootsNostrEventBuilderUnchecked::job_feedback(feedback_data)
.tags(tags.unwrap_or_default())
.allow_self_tagging();
- Ok(RadrootsNostrGenericEventBuilder::from_unchecked(builder))
+ Ok(GenericBuilder::from_unchecked(builder))
}
diff --git a/crates/nostr/src/events/metadata.rs b/crates/nostr/src/events/metadata.rs
@@ -1,7 +1,7 @@
//! Sealed authoring for validated NIP-01 profile metadata events.
#[cfg(feature = "events")]
-use crate::error::RadrootsNostrError;
+use crate::error::Error;
#[cfg(feature = "events")]
use crate::types::RadrootsNostrEvent;
#[cfg(feature = "events")]
@@ -18,12 +18,12 @@ use radroots_event_codec::encode::profile::authored_profile_to_wire_parts;
/// BUD-02 upload completion before signing or publication.
#[cfg(feature = "events")]
#[must_use = "Profile event builders must be signed or published"]
-pub struct RadrootsNostrProfileEventBuilder {
+pub struct ProfileBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
#[cfg(feature = "events")]
-impl RadrootsNostrProfileEventBuilder {
+impl ProfileBuilder {
/// Sets the event timestamp without changing the validated Profile shape.
pub fn custom_created_at(mut self, created_at: RadrootsNostrTimestamp) -> Self {
self.inner = self.inner.custom_created_at(created_at);
@@ -31,21 +31,15 @@ impl RadrootsNostrProfileEventBuilder {
}
/// Signs the validated Profile directly with local keys.
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
/// Builds a sealed kind-0 event from the strict authored Profile contract.
#[cfg(feature = "events")]
-pub fn radroots_nostr_build_profile_event(
- profile: &AuthoredProfile,
-) -> Result<RadrootsNostrProfileEventBuilder, RadrootsNostrError> {
+pub fn build_profile_event(profile: &AuthoredProfile) -> Result<ProfileBuilder, Error> {
let parts = authored_profile_to_wire_parts(profile)?;
- let inner =
- crate::events::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?;
- Ok(RadrootsNostrProfileEventBuilder { inner })
+ let inner = crate::events::build_event_unchecked(parts.kind, parts.content, parts.tags)?;
+ Ok(ProfileBuilder { inner })
}
diff --git a/crates/nostr/src/events/mod.rs b/crates/nostr/src/events/mod.rs
@@ -23,19 +23,19 @@ extern crate alloc;
use alloc::{string::String, vec::Vec};
#[cfg(any(feature = "events", test))]
-use crate::error::RadrootsNostrError;
+use crate::error::Error;
#[cfg(any(feature = "events", test))]
use crate::types::{
RadrootsNostrEventBuilderUnchecked, RadrootsNostrKind, RadrootsNostrTag, RadrootsNostrTagKind,
};
#[cfg(any(feature = "events", test))]
-pub(crate) fn radroots_nostr_build_event_unchecked(
+pub(crate) fn build_event_unchecked(
kind_u32: u32,
content: impl Into<String>,
tag_slices: Vec<Vec<String>>,
-) -> Result<RadrootsNostrEventBuilderUnchecked, RadrootsNostrError> {
- let kind = u16::try_from(kind_u32).map_err(|_| RadrootsNostrError::KindOutOfRange {
+) -> Result<RadrootsNostrEventBuilderUnchecked, Error> {
+ let kind = u16::try_from(kind_u32).map_err(|_| Error::KindOutOfRange {
kind: kind_u32,
max: u16::MAX,
})?;
@@ -62,8 +62,8 @@ pub(crate) fn radroots_nostr_build_event_unchecked(
mod tests {
use alloc::{vec, vec::Vec};
- use super::radroots_nostr_build_event_unchecked;
- use crate::error::RadrootsNostrError;
+ use super::build_event_unchecked;
+ use crate::error::Error;
use crate::test_fixtures::FIXTURE_ALICE_PUBLIC_KEY_HEX;
use crate::types::{RadrootsNostrPublicKey, RadrootsNostrTagKind};
@@ -76,7 +76,7 @@ mod tests {
vec!["p".to_string(), pubkey_hex.to_string()],
];
- let builder = radroots_nostr_build_event_unchecked(1, "test", tags).expect("builder");
+ let builder = build_event_unchecked(1, "test", tags).expect("builder");
let event = builder.build(pubkey);
let has_self_tag = event.tags.iter().any(|tag| {
@@ -93,7 +93,7 @@ mod tests {
#[test]
fn build_event_accepts_maximum_nip01_kind() {
- let builder = radroots_nostr_build_event_unchecked(u32::from(u16::MAX), "test", Vec::new())
+ let builder = build_event_unchecked(u32::from(u16::MAX), "test", Vec::new())
.expect("maximum NIP-01 kind");
let event = builder
.build(RadrootsNostrPublicKey::from_hex(FIXTURE_ALICE_PUBLIC_KEY_HEX).expect("pubkey"));
@@ -104,8 +104,8 @@ mod tests {
fn build_event_rejects_kind_overflow() {
let kind = u32::from(u16::MAX) + 1;
assert!(matches!(
- radroots_nostr_build_event_unchecked(kind, "test", Vec::new()),
- Err(RadrootsNostrError::KindOutOfRange {
+ build_event_unchecked(kind, "test", Vec::new()),
+ Err(Error::KindOutOfRange {
kind: actual,
max: u16::MAX
}) if actual == kind
diff --git a/crates/nostr/src/events/post.rs b/crates/nostr/src/events/post.rs
@@ -1,7 +1,7 @@
//! Typed authoring and filtering for supported Radroots social root events.
#[cfg(feature = "events")]
-use crate::error::RadrootsNostrError;
+use crate::error::Error;
#[cfg(feature = "events")]
use crate::types::RadrootsNostrEventBuilderUnchecked;
#[cfg(feature = "events")]
@@ -23,12 +23,12 @@ use radroots_event_codec::encode::post::{
/// mutation. Construct it through one of the typed post authoring functions.
#[cfg(feature = "events")]
#[must_use = "post event builders must be signed or published"]
-pub struct RadrootsNostrPostEventBuilder {
+pub struct PostBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
#[cfg(feature = "events")]
-impl RadrootsNostrPostEventBuilder {
+impl PostBuilder {
/// Sets the event timestamp without changing the validated post shape.
pub fn custom_created_at(mut self, created_at: RadrootsNostrTimestamp) -> Self {
self.inner = self.inner.custom_created_at(created_at);
@@ -36,39 +36,27 @@ impl RadrootsNostrPostEventBuilder {
}
/// Signs the validated post directly with local keys.
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
#[cfg(feature = "events")]
-pub fn radroots_nostr_build_update_event(
- update: &AuthoredUpdate,
-) -> Result<RadrootsNostrPostEventBuilder, RadrootsNostrError> {
+pub fn build_update_event(update: &AuthoredUpdate) -> Result<PostBuilder, Error> {
builder_from_wire_parts(authored_update_to_wire_parts(update))
}
#[cfg(feature = "events")]
-pub fn radroots_nostr_build_photo_update_event(
- photo: &AuthoredPhotoUpdate,
-) -> Result<RadrootsNostrPostEventBuilder, RadrootsNostrError> {
+pub fn build_photo_update_event(photo: &AuthoredPhotoUpdate) -> Result<PostBuilder, Error> {
builder_from_wire_parts(authored_photo_update_to_wire_parts(photo))
}
#[cfg(feature = "events")]
-pub fn radroots_nostr_build_ask_event(
- ask: &AuthoredAsk,
-) -> Result<RadrootsNostrPostEventBuilder, RadrootsNostrError> {
+pub fn build_ask_event(ask: &AuthoredAsk) -> Result<PostBuilder, Error> {
builder_from_wire_parts(authored_ask_to_wire_parts(ask))
}
-pub fn radroots_nostr_post_events_filter(
- limit: Option<u16>,
- since_unix: Option<u64>,
-) -> RadrootsNostrFilter {
+pub fn post_events_filter(limit: Option<u16>, since_unix: Option<u64>) -> RadrootsNostrFilter {
let mut filter = RadrootsNostrFilter::new().kind(RadrootsNostrKind::TextNote);
if let Some(limit) = limit {
filter = filter.limit(limit.into());
@@ -80,10 +68,7 @@ pub fn radroots_nostr_post_events_filter(
}
#[cfg(feature = "events")]
-fn builder_from_wire_parts(
- parts: Nip01EventWireParts,
-) -> Result<RadrootsNostrPostEventBuilder, RadrootsNostrError> {
- let inner =
- crate::events::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?;
- Ok(RadrootsNostrPostEventBuilder { inner })
+fn builder_from_wire_parts(parts: Nip01EventWireParts) -> Result<PostBuilder, Error> {
+ let inner = crate::events::build_event_unchecked(parts.kind, parts.content, parts.tags)?;
+ Ok(PostBuilder { inner })
}
diff --git a/crates/nostr/src/events/reply.rs b/crates/nostr/src/events/reply.rs
@@ -1,7 +1,7 @@
//! Sealed authoring for strict marked NIP-10 Reply events.
use crate::{
- error::RadrootsNostrError,
+ error::Error,
types::{
RadrootsNostrEvent, RadrootsNostrEventBuilderUnchecked, RadrootsNostrKeys,
RadrootsNostrTimestamp,
@@ -15,42 +15,34 @@ use radroots_event_codec::encode::reply::authored_nip10_reply_to_wire_parts;
/// The wrapper exposes no raw builder conversion or tag/content mutation.
///
/// ```compile_fail
-/// use radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder;
+/// use radroots_nostr::event::Nip10ReplyBuilder;
///
-/// fn expose_raw_builder(builder: RadrootsNostrNip10ReplyEventBuilder) {
+/// fn expose_raw_builder(builder: Nip10ReplyBuilder) {
/// let _: nostr::EventBuilder = builder.into();
/// }
/// ```
#[must_use = "NIP-10 Reply builders must be signed or published"]
-pub struct RadrootsNostrNip10ReplyEventBuilder {
+pub struct Nip10ReplyBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
-impl RadrootsNostrNip10ReplyEventBuilder {
+impl Nip10ReplyBuilder {
pub fn custom_created_at(mut self, created_at: RadrootsNostrTimestamp) -> Self {
self.inner = self.inner.custom_created_at(created_at);
self
}
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
Ok(self.inner.sign_with_keys(keys)?)
}
}
-pub fn radroots_nostr_build_nip10_reply_event(
- reply: &AuthoredNip10Reply,
-) -> Result<RadrootsNostrNip10ReplyEventBuilder, RadrootsNostrError> {
+pub fn build_nip10_reply_event(reply: &AuthoredNip10Reply) -> Result<Nip10ReplyBuilder, Error> {
let parts = authored_nip10_reply_to_wire_parts(reply);
builder_from_wire_parts(parts)
}
-fn builder_from_wire_parts(
- parts: Nip01EventWireParts,
-) -> Result<RadrootsNostrNip10ReplyEventBuilder, RadrootsNostrError> {
- let inner =
- crate::events::radroots_nostr_build_event_unchecked(parts.kind, parts.content, parts.tags)?;
- Ok(RadrootsNostrNip10ReplyEventBuilder { inner })
+fn builder_from_wire_parts(parts: Nip01EventWireParts) -> Result<Nip10ReplyBuilder, Error> {
+ let inner = crate::events::build_event_unchecked(parts.kind, parts.content, parts.tags)?;
+ Ok(Nip10ReplyBuilder { inner })
}
diff --git a/crates/nostr/src/filter.rs b/crates/nostr/src/filter.rs
@@ -3,7 +3,7 @@
//! Filters are passive protocol values. Constructing one does not subscribe,
//! contact a relay, install a clock, or retain runtime state.
-use crate::error::RadrootsNostrError;
+use crate::Error;
use crate::event::Kind;
#[cfg(feature = "std")]
use crate::event::Timestamp;
@@ -12,34 +12,30 @@ use alloc::{string::String, string::ToString, vec::Vec};
/// Upstream Nostr filter used only at the explicit protocol boundary.
pub type Filter = nostr::Filter;
-pub fn radroots_nostr_filter_tag(
- filter: Filter,
- tag: &str,
- values: Vec<String>,
-) -> Result<Filter, RadrootsNostrError> {
+pub fn with_tag(filter: Filter, tag: &str, values: Vec<String>) -> Result<Filter, Error> {
let mut chars = tag.chars();
let tag_char = chars
.next()
- .ok_or_else(|| RadrootsNostrError::FilterTagError("tag is empty".to_string()))?;
+ .ok_or_else(|| Error::FilterTagError("tag is empty".to_string()))?;
if chars.next().is_some() {
- return Err(RadrootsNostrError::FilterTagError(
+ return Err(Error::FilterTagError(
"tag must be a single letter".to_string(),
));
}
let tag_key = nostr::filter::SingleLetterTag::from_char(tag_char)
- .map_err(|err| RadrootsNostrError::FilterTagError(err.to_string()))?;
+ .map_err(|err| Error::FilterTagError(err.to_string()))?;
Ok(filter.custom_tags(tag_key, values))
}
-pub fn radroots_nostr_kind(kind: u16) -> Kind {
+pub fn kind(kind: u16) -> Kind {
Kind::Custom(kind)
}
-pub fn radroots_nostr_filter_kind(kind: u16) -> Filter {
+pub fn for_kind(kind: u16) -> Filter {
Filter::new().kind(Kind::Custom(kind))
}
#[cfg(feature = "std")]
-pub fn radroots_nostr_filter_new_events(filter: Filter) -> Filter {
+pub fn since_now(filter: Filter) -> Filter {
filter.since(Timestamp::now())
}
diff --git a/crates/nostr/src/job_adapter.rs b/crates/nostr/src/job_adapter.rs
@@ -10,13 +10,13 @@ use radroots_event::envelope::kind::KIND_PROFILE;
use radroots_event_codec::decode::job::{JobEventBorrow, JobEventLike};
#[derive(Clone, Debug)]
-pub struct RadrootsNostrEventAdapter<'a> {
+pub struct EventAdapter<'a> {
evt: &'a RadrootsNostrEvent,
id_hex: String,
author_hex: String,
}
-impl<'a> RadrootsNostrEventAdapter<'a> {
+impl<'a> EventAdapter<'a> {
#[inline]
pub fn new(evt: &'a RadrootsNostrEvent) -> Self {
Self {
@@ -36,7 +36,7 @@ impl<'a> RadrootsNostrEventAdapter<'a> {
}
}
-impl<'a> JobEventBorrow<'a> for RadrootsNostrEventAdapter<'a> {
+impl<'a> JobEventBorrow<'a> for EventAdapter<'a> {
#[inline]
fn raw_id(&'a self) -> String {
self.id_hex.clone()
@@ -58,7 +58,7 @@ impl<'a> JobEventBorrow<'a> for RadrootsNostrEventAdapter<'a> {
}
}
-impl JobEventLike for RadrootsNostrEventAdapter<'_> {
+impl JobEventLike for EventAdapter<'_> {
fn raw_id(&self) -> String {
self.id_hex.clone()
}
diff --git a/crates/nostr/src/lib.rs b/crates/nostr/src/lib.rs
@@ -9,26 +9,28 @@ extern crate core as std;
#[cfg(feature = "blossom")]
pub mod blossom;
-pub mod error;
+mod error;
pub mod event;
-pub mod events;
+#[cfg(feature = "events")]
+mod events;
pub mod filter;
pub mod key;
pub mod tag;
mod tags;
-pub mod types;
-pub mod util;
+mod types;
+#[cfg(feature = "events")]
+mod util;
-pub use error::RadrootsNostrError as Error;
+pub use error::Error;
#[cfg(test)]
mod test_fixtures;
-#[cfg(feature = "codec")]
-pub mod codec_adapters;
+#[cfg(feature = "events")]
+mod codec_adapters;
-#[cfg(feature = "codec")]
-pub mod job_adapter;
+#[cfg(feature = "events")]
+mod job_adapter;
#[cfg(feature = "nip17")]
pub mod nip17;
@@ -37,11 +39,11 @@ pub mod nip17;
pub mod signing;
#[cfg(feature = "events")]
-pub mod event_adapters;
+mod event_adapters;
-#[cfg(feature = "events")]
-pub mod draft_signing;
+#[cfg(feature = "signing")]
+mod draft_signing;
#[cfg(feature = "events")]
mod event_convert;
#[cfg(feature = "events")]
-pub mod event_verify;
+mod event_verify;
diff --git a/crates/nostr/src/nip17.rs b/crates/nostr/src/nip17.rs
@@ -27,7 +27,7 @@ use radroots_event_codec::encode::{EventEncodeError, message as message_encode};
/// Stable, source-redacted failures from the focused NIP-17 adapter.
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
-pub enum RadrootsNip17Error {
+pub enum Error {
MessageEncode,
MessageDecode,
GiftWrap,
@@ -36,7 +36,7 @@ pub enum RadrootsNip17Error {
UnsupportedRumorKind { kind: u32 },
}
-impl RadrootsNip17Error {
+impl Error {
/// Returns a stable machine-readable failure code.
#[must_use]
pub const fn code(&self) -> &'static str {
@@ -51,7 +51,7 @@ impl RadrootsNip17Error {
}
}
-impl core::fmt::Display for RadrootsNip17Error {
+impl core::fmt::Display for Error {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::MessageEncode => formatter.write_str("failed to encode NIP-17 message"),
@@ -66,71 +66,71 @@ impl core::fmt::Display for RadrootsNip17Error {
}
}
-impl core::error::Error for RadrootsNip17Error {}
+impl core::error::Error for Error {}
-impl From<EventEncodeError> for RadrootsNip17Error {
+impl From<EventEncodeError> for Error {
fn from(_: EventEncodeError) -> Self {
Self::MessageEncode
}
}
-impl From<EventParseError> for RadrootsNip17Error {
+impl From<EventParseError> for Error {
fn from(_: EventParseError) -> Self {
Self::MessageDecode
}
}
-impl From<nip59::Error> for RadrootsNip17Error {
+impl From<nip59::Error> for Error {
fn from(_: nip59::Error) -> Self {
Self::GiftWrap
}
}
-impl From<nostr::event::builder::Error> for RadrootsNip17Error {
+impl From<nostr::event::builder::Error> for Error {
fn from(_: nostr::event::builder::Error) -> Self {
Self::GiftWrap
}
}
-impl From<nostr::signer::SignerError> for RadrootsNip17Error {
+impl From<nostr::signer::SignerError> for Error {
fn from(_: nostr::signer::SignerError) -> Self {
Self::Signer
}
}
-impl From<nostr::key::Error> for RadrootsNip17Error {
+impl From<nostr::key::Error> for Error {
fn from(_: nostr::key::Error) -> Self {
Self::InvalidRecipient
}
}
#[derive(Clone)]
-pub enum RadrootsNip17Rumor {
+pub enum Rumor {
Message(RadrootsParsedData<Message>),
MessageFile(Box<RadrootsParsedData<MessageFile>>),
}
-impl core::fmt::Debug for RadrootsNip17Rumor {
+impl core::fmt::Debug for Rumor {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Message(_) => formatter
- .debug_struct("RadrootsNip17Rumor::Message")
+ .debug_struct("Rumor::Message")
.finish_non_exhaustive(),
Self::MessageFile(_) => formatter
- .debug_struct("RadrootsNip17Rumor::MessageFile")
+ .debug_struct("Rumor::MessageFile")
.finish_non_exhaustive(),
}
}
}
#[derive(Clone, Debug)]
-pub struct RadrootsNip17WrapOptions {
- pub include_sender: bool,
- pub rumor_created_at: Option<u64>,
- pub gift_wrap_tags: Vec<Vec<String>>,
+pub struct WrapOptions {
+ include_sender: bool,
+ rumor_created_at: Option<u64>,
+ gift_wrap_tags: Vec<Vec<String>>,
}
-impl Default for RadrootsNip17WrapOptions {
+impl Default for WrapOptions {
fn default() -> Self {
Self {
include_sender: true,
@@ -140,6 +140,38 @@ impl Default for RadrootsNip17WrapOptions {
}
}
+impl WrapOptions {
+ #[must_use]
+ pub fn include_sender(mut self, include_sender: bool) -> Self {
+ self.include_sender = include_sender;
+ self
+ }
+
+ #[must_use]
+ pub fn with_rumor_created_at(mut self, created_at: u64) -> Self {
+ self.rumor_created_at = Some(created_at);
+ self
+ }
+
+ #[must_use]
+ pub fn with_gift_wrap_tags(mut self, tags: Vec<Vec<String>>) -> Self {
+ self.gift_wrap_tags = tags;
+ self
+ }
+
+ pub const fn includes_sender(&self) -> bool {
+ self.include_sender
+ }
+
+ pub const fn rumor_created_at(&self) -> Option<u64> {
+ self.rumor_created_at
+ }
+
+ pub fn gift_wrap_tags(&self) -> &[Vec<String>] {
+ &self.gift_wrap_tags
+ }
+}
+
fn tags_from_slices(tag_slices: &[Vec<String>]) -> Vec<Tag> {
let mut tags = Vec::with_capacity(tag_slices.len());
for slice in tag_slices {
@@ -157,9 +189,9 @@ fn rumor_from_parts(
parts: Nip01EventWireParts,
author: PublicKey,
created_at: Option<u64>,
-) -> Result<UnsignedEvent, RadrootsNip17Error> {
- let kind = u16::try_from(parts.kind)
- .map_err(|_| RadrootsNip17Error::UnsupportedRumorKind { kind: parts.kind })?;
+) -> Result<UnsignedEvent, Error> {
+ let kind =
+ u16::try_from(parts.kind).map_err(|_| Error::UnsupportedRumorKind { kind: parts.kind })?;
let tags = tags_from_slices(&parts.tags);
let timestamp = match created_at {
Some(ts) => Timestamp::from_secs(ts),
@@ -172,7 +204,7 @@ fn rumor_from_parts(
fn parse_recipients(
recipients: &[radroots_event::social::message::MessageRecipient],
-) -> Result<Vec<PublicKey>, RadrootsNip17Error> {
+) -> Result<Vec<PublicKey>, Error> {
let mut out = Vec::with_capacity(recipients.len());
for recipient in recipients {
out.push(recipient.public_key.parse::<PublicKey>()?);
@@ -191,8 +223,8 @@ async fn wrap_rumor<T>(
signer: &T,
rumor: UnsignedEvent,
mut recipients: Vec<PublicKey>,
- options: &RadrootsNip17WrapOptions,
-) -> Result<Vec<Event>, RadrootsNip17Error>
+ options: &WrapOptions,
+) -> Result<Vec<Event>, Error>
where
T: NostrSigner,
{
@@ -211,11 +243,11 @@ where
Ok(out)
}
-pub async fn radroots_nostr_wrap_message<T>(
+pub async fn wrap_message<T>(
signer: &T,
message: &Message,
- options: RadrootsNip17WrapOptions,
-) -> Result<Vec<Event>, RadrootsNip17Error>
+ options: WrapOptions,
+) -> Result<Vec<Event>, Error>
where
T: NostrSigner,
{
@@ -226,11 +258,11 @@ where
wrap_rumor(signer, rumor, recipients, &options).await
}
-pub async fn radroots_nostr_wrap_message_file<T>(
+pub async fn wrap_message_file<T>(
signer: &T,
message: &MessageFile,
- options: RadrootsNip17WrapOptions,
-) -> Result<Vec<Event>, RadrootsNip17Error>
+ options: WrapOptions,
+) -> Result<Vec<Event>, Error>
where
T: NostrSigner,
{
@@ -241,10 +273,7 @@ where
wrap_rumor(signer, rumor, recipients, &options).await
}
-pub async fn radroots_nostr_unwrap_gift_wrap<T>(
- signer: &T,
- gift_wrap: &Event,
-) -> Result<RadrootsNip17Rumor, RadrootsNip17Error>
+pub async fn unwrap_gift_wrap<T>(signer: &T, gift_wrap: &Event) -> Result<Rumor, Error>
where
T: NostrSigner,
{
@@ -266,7 +295,7 @@ where
KIND_MESSAGE => {
let metadata =
message_decode::data_from_event(id, author, published_at, kind, content, tags)?;
- Ok(RadrootsNip17Rumor::Message(metadata))
+ Ok(Rumor::Message(metadata))
}
KIND_MESSAGE_FILE => {
let metadata = message_file_decode::data_from_event(
@@ -277,9 +306,9 @@ where
content,
tags,
)?;
- Ok(RadrootsNip17Rumor::MessageFile(Box::new(metadata)))
+ Ok(Rumor::MessageFile(Box::new(metadata)))
}
- other => Err(RadrootsNip17Error::UnsupportedRumorKind { kind: other }),
+ other => Err(Error::UnsupportedRumorKind { kind: other }),
}
}
@@ -325,25 +354,22 @@ mod tests {
author,
Some(1_700_000_000),
),
- Err(RadrootsNip17Error::UnsupportedRumorKind { kind }) if kind == overflow
+ Err(Error::UnsupportedRumorKind { kind }) if kind == overflow
));
}
#[test]
fn adapter_error_codes_are_stable_and_source_redacted() {
let errors = [
- RadrootsNip17Error::MessageEncode,
- RadrootsNip17Error::MessageDecode,
- RadrootsNip17Error::GiftWrap,
- RadrootsNip17Error::Signer,
- RadrootsNip17Error::InvalidRecipient,
- RadrootsNip17Error::UnsupportedRumorKind { kind: 70_000 },
+ Error::MessageEncode,
+ Error::MessageDecode,
+ Error::GiftWrap,
+ Error::Signer,
+ Error::InvalidRecipient,
+ Error::UnsupportedRumorKind { kind: 70_000 },
];
assert_eq!(
- errors
- .iter()
- .map(RadrootsNip17Error::code)
- .collect::<Vec<_>>(),
+ errors.iter().map(Error::code).collect::<Vec<_>>(),
vec![
"message_encode",
"message_decode",
@@ -373,22 +399,16 @@ mod tests {
reply_to: None,
subject: None,
};
- let options = RadrootsNip17WrapOptions {
- include_sender: false,
- rumor_created_at: Some(1700000000),
- gift_wrap_tags: Vec::new(),
- };
+ let options = WrapOptions::default()
+ .include_sender(false)
+ .with_rumor_created_at(1_700_000_000);
- let events = radroots_nostr_wrap_message(&sender, &message, options)
- .await
- .unwrap();
+ let events = wrap_message(&sender, &message, options).await.unwrap();
assert_eq!(events.len(), 1);
- let rumor = radroots_nostr_unwrap_gift_wrap(&receiver, &events[0])
- .await
- .unwrap();
+ let rumor = unwrap_gift_wrap(&receiver, &events[0]).await.unwrap();
match rumor {
- RadrootsNip17Rumor::Message(metadata) => {
+ Rumor::Message(metadata) => {
assert_eq!(metadata.data.content, "hello");
assert_eq!(metadata.data.recipients.len(), 1);
}
@@ -420,20 +440,14 @@ mod tests {
thumb: None,
fallbacks: Vec::new(),
};
- let options = RadrootsNip17WrapOptions {
- include_sender: false,
- rumor_created_at: Some(1700000001),
- gift_wrap_tags: Vec::new(),
- };
+ let options = WrapOptions::default()
+ .include_sender(false)
+ .with_rumor_created_at(1_700_000_001);
- let events = radroots_nostr_wrap_message_file(&sender, &message, options)
- .await
- .unwrap();
+ let events = wrap_message_file(&sender, &message, options).await.unwrap();
assert_eq!(events.len(), 1);
- let rumor = radroots_nostr_unwrap_gift_wrap(&receiver, &events[0])
- .await
- .unwrap();
+ let rumor = unwrap_gift_wrap(&receiver, &events[0]).await.unwrap();
let rendered = format!("{rumor:?}");
for private_value in [
message.file_url.as_str(),
@@ -444,7 +458,7 @@ mod tests {
assert!(!rendered.contains(private_value));
}
match rumor {
- RadrootsNip17Rumor::MessageFile(metadata) => {
+ Rumor::MessageFile(metadata) => {
assert_eq!(metadata.data.file_url, message.file_url);
assert_eq!(metadata.data.encrypted_hash, message.encrypted_hash);
}
diff --git a/crates/nostr/src/signing.rs b/crates/nostr/src/signing.rs
@@ -17,11 +17,11 @@ use radroots_signing::{
status::{SignProgress, SignProgressStage, SignerAvailability},
};
-use crate::{
- draft_signing::radroots_nostr_sign_frozen_draft, error::RadrootsNostrError, key::SecretKey,
-};
+use crate::{Error as NostrError, key::SecretKey};
use radroots_identity::PublicKey;
+pub use crate::draft_signing::sign_frozen_draft;
+
type Clock = fn() -> Result<u64, SigningError>;
/// A local Nostr key-backed signer adapter.
@@ -97,8 +97,8 @@ impl Signer for LocalSigner {
&SignProgress::stage(SignProgressStage::Validating)
.expect("validating progress never requires a challenge"),
);
- let signed_event = radroots_nostr_sign_frozen_draft(&self.keys, request.draft())
- .map_err(normalize_nostr_error)?;
+ let signed_event =
+ sign_frozen_draft(&self.keys, request.draft()).map_err(normalize_nostr_error)?;
request.report_progress(
&SignProgress::stage(SignProgressStage::VerifyingOutput)
.expect("verification progress never requires a challenge"),
@@ -125,10 +125,10 @@ fn system_time_unix() -> Result<u64, SigningError> {
.map_err(|source| SigningError::with_source(Kind::InternalError, source))
}
-fn normalize_nostr_error(source: RadrootsNostrError) -> SigningError {
+fn normalize_nostr_error(source: NostrError) -> SigningError {
let kind = match &source {
- RadrootsNostrError::FrozenDraftPubkeyMismatch { .. } => Kind::AuthorizationDenied,
- RadrootsNostrError::FrozenDraftEventIdMismatch { .. } => Kind::SignerOutputInvalid,
+ NostrError::FrozenDraftPubkeyMismatch { .. } => Kind::AuthorizationDenied,
+ NostrError::FrozenDraftEventIdMismatch { .. } => Kind::SignerOutputInvalid,
_ => Kind::InternalError,
};
SigningError::with_source(kind, source)
diff --git a/crates/nostr/src/tag.rs b/crates/nostr/src/tag.rs
@@ -14,12 +14,13 @@ pub type TagKind<'a> = nostr::TagKind<'a>;
/// Upstream standardized Nostr tag used only at the explicit protocol boundary.
pub type TagStandard = nostr::TagStandard;
+pub use crate::error::ResolveError;
pub use crate::tags::{
- radroots_nostr_tag_at_value, radroots_nostr_tag_first_value, radroots_nostr_tag_match_geohash,
- radroots_nostr_tag_match_l, radroots_nostr_tag_match_location,
- radroots_nostr_tag_match_summary, radroots_nostr_tag_match_title,
- radroots_nostr_tag_relays_parse, radroots_nostr_tag_slice, radroots_nostr_tags_match,
- radroots_nostr_tags_resolve,
+ tag_at_value as value_at, tag_first_value as first_value, tag_match_geohash as match_geohash,
+ tag_match_l as match_location_coordinate, tag_match_location as match_location,
+ tag_match_summary as match_summary, tag_match_title as match_title,
+ tag_relays_parse as relay_urls, tag_slice as values_from, tags_match as match_parts,
+ tags_resolve as resolve,
};
/// Parses canonical tag parts into the explicit Nostr tag boundary value.
diff --git a/crates/nostr/src/tags.rs b/crates/nostr/src/tags.rs
@@ -7,13 +7,13 @@ use alloc::{
use nostr::nips::nip04;
-use crate::error::RadrootsNostrTagsResolveError;
+use crate::error::ResolveError;
use crate::types::{
RadrootsNostrEvent, RadrootsNostrKeys, RadrootsNostrPublicKey, RadrootsNostrRelayUrl,
RadrootsNostrTag, RadrootsNostrTagKind, RadrootsNostrTagStandard,
};
-pub fn radroots_nostr_tag_first_value(tag: &RadrootsNostrTag, key: &str) -> Option<String> {
+pub fn tag_first_value(tag: &RadrootsNostrTag, key: &str) -> Option<String> {
if tag.kind() == RadrootsNostrTagKind::custom(key) {
tag.content().map(|v| v.to_string())
} else {
@@ -21,31 +21,29 @@ pub fn radroots_nostr_tag_first_value(tag: &RadrootsNostrTag, key: &str) -> Opti
}
}
-pub fn radroots_nostr_tag_at_value(tag: &RadrootsNostrTag, index: usize) -> Option<String> {
+pub fn tag_at_value(tag: &RadrootsNostrTag, index: usize) -> Option<String> {
tag.as_slice().get(index).cloned()
}
-pub fn radroots_nostr_tag_slice(tag: &RadrootsNostrTag, start: usize) -> Option<Vec<String>> {
+pub fn tag_slice(tag: &RadrootsNostrTag, start: usize) -> Option<Vec<String>> {
tag.as_slice().get(start..).map(|s| s.to_vec())
}
-pub fn radroots_nostr_tag_relays_parse(
- tag: &RadrootsNostrTag,
-) -> Option<&Vec<RadrootsNostrRelayUrl>> {
+pub fn tag_relays_parse(tag: &RadrootsNostrTag) -> Option<&Vec<RadrootsNostrRelayUrl>> {
match tag.as_standardized()? {
RadrootsNostrTagStandard::Relays(urls) => Some(urls),
_ => None,
}
}
-pub fn radroots_nostr_tags_match(tag: &RadrootsNostrTag) -> Option<(&str, &[String])> {
+pub fn tags_match(tag: &RadrootsNostrTag) -> Option<(&str, &[String])> {
let values = tag.as_slice();
values
.split_first()
.map(|(key, tag_values)| (key.as_str(), tag_values))
}
-pub fn radroots_nostr_tag_match_l(tag: &RadrootsNostrTag) -> Option<(&str, f64)> {
+pub fn tag_match_l(tag: &RadrootsNostrTag) -> Option<(&str, f64)> {
let values = tag.as_slice();
if values.len() >= 3
&& values[0].eq_ignore_ascii_case("l")
@@ -56,7 +54,7 @@ pub fn radroots_nostr_tag_match_l(tag: &RadrootsNostrTag) -> Option<(&str, f64)>
None
}
-pub fn radroots_nostr_tag_match_location(tag: &RadrootsNostrTag) -> Option<(&str, &str, &str)> {
+pub fn tag_match_location(tag: &RadrootsNostrTag) -> Option<(&str, &str, &str)> {
let values = tag.as_slice();
if values.len() >= 4 && values[0] == "location" {
Some((values[1].as_str(), values[2].as_str(), values[3].as_str()))
@@ -65,31 +63,31 @@ pub fn radroots_nostr_tag_match_location(tag: &RadrootsNostrTag) -> Option<(&str
}
}
-pub fn radroots_nostr_tag_match_geohash(tag: &RadrootsNostrTag) -> Option<String> {
+pub fn tag_match_geohash(tag: &RadrootsNostrTag) -> Option<String> {
match tag.as_standardized()? {
RadrootsNostrTagStandard::Geohash(geohash) => Some(geohash.clone()),
_ => None,
}
}
-pub fn radroots_nostr_tag_match_title(tag: &RadrootsNostrTag) -> Option<String> {
+pub fn tag_match_title(tag: &RadrootsNostrTag) -> Option<String> {
match tag.as_standardized()? {
RadrootsNostrTagStandard::Title(title) => Some(title.clone()),
_ => None,
}
}
-pub fn radroots_nostr_tag_match_summary(tag: &RadrootsNostrTag) -> Option<String> {
+pub fn tag_match_summary(tag: &RadrootsNostrTag) -> Option<String> {
match tag.as_standardized()? {
RadrootsNostrTagStandard::Summary(summary) => Some(summary.clone()),
_ => None,
}
}
-pub fn radroots_nostr_tags_resolve(
+pub fn tags_resolve(
event: &RadrootsNostrEvent,
keys: &RadrootsNostrKeys,
-) -> Result<Vec<RadrootsNostrTag>, RadrootsNostrTagsResolveError> {
+) -> Result<Vec<RadrootsNostrTag>, ResolveError> {
if !event
.tags
.iter()
@@ -107,12 +105,12 @@ pub fn radroots_nostr_tags_resolve(
None
}
})
- .ok_or_else(|| RadrootsNostrTagsResolveError::MissingPTag(Box::new(event.clone())))?;
+ .ok_or_else(|| ResolveError::MissingPTag(Box::new(event.clone())))?;
if recipient != keys.public_key() {
- return Err(RadrootsNostrTagsResolveError::NotRecipient);
+ return Err(ResolveError::NotRecipient);
}
let cleartext = nip04::decrypt(keys.secret_key(), &event.pubkey, &event.content)
- .map_err(|e| RadrootsNostrTagsResolveError::DecryptionError(e.to_string()))?;
+ .map_err(|e| ResolveError::DecryptionError(e.to_string()))?;
let decrypted_tags: nostr::event::tag::list::Tags = serde_json::from_str(&cleartext)?;
Ok(decrypted_tags.to_vec())
}
diff --git a/crates/nostr/src/types.rs b/crates/nostr/src/types.rs
@@ -6,31 +6,31 @@
#![forbid(unsafe_code)]
-#[cfg(feature = "std")]
-use crate::error::RadrootsNostrError;
-#[cfg(feature = "std")]
+#[cfg(all(feature = "events", feature = "std"))]
+use crate::error::Error;
+#[cfg(all(feature = "events", feature = "std"))]
use radroots_event::listing::classified::{
ClassifiedListingPartition, classify_classified_listing_marker_names,
};
+pub(crate) use crate::event::Event as RadrootsNostrEvent;
#[cfg(feature = "events")]
pub(crate) use crate::event::Metadata as RadrootsNostrMetadata;
+#[cfg(feature = "events")]
pub(crate) use crate::event::{
- Event as RadrootsNostrEvent, EventId as RadrootsNostrEventId, Kind as RadrootsNostrKind,
- Timestamp as RadrootsNostrTimestamp,
+ EventId as RadrootsNostrEventId, Kind as RadrootsNostrKind, Timestamp as RadrootsNostrTimestamp,
};
+#[cfg(feature = "events")]
pub(crate) use crate::filter::Filter as RadrootsNostrFilter;
pub(crate) use crate::tag::{
Tag as RadrootsNostrTag, TagKind as RadrootsNostrTagKind,
TagStandard as RadrootsNostrTagStandard,
};
+#[cfg(feature = "events")]
pub(crate) type RadrootsNostrEventBuilderUnchecked = nostr::EventBuilder;
-pub type RadrootsNostrKeys = nostr::Keys;
-pub type RadrootsNostrPublicKey = nostr::PublicKey;
-pub type RadrootsNostrRelayUrl = nostr::RelayUrl;
-pub type RadrootsNostrSecretKey = nostr::SecretKey;
-pub type RadrootsNostrSubscriptionId = nostr::SubscriptionId;
-pub type RadrootsNostrUrl = nostr::Url;
+pub(crate) type RadrootsNostrKeys = nostr::Keys;
+pub(crate) type RadrootsNostrPublicKey = nostr::PublicKey;
+pub(crate) type RadrootsNostrRelayUrl = nostr::RelayUrl;
/// A checked generic event prepared for an external signer.
///
@@ -40,19 +40,21 @@ pub type RadrootsNostrUrl = nostr::Url;
/// deserialization boundary.
///
/// ```compile_fail
-/// use radroots_nostr::types::RadrootsNostrExternalSigningRequest;
+/// use radroots_nostr::event::ExternalSigningRequest;
///
-/// let _: RadrootsNostrExternalSigningRequest =
+/// let _: ExternalSigningRequest =
/// serde_json::from_str("{}").expect("request");
/// ```
#[must_use = "external signing requests must be completed by a signer"]
-pub struct RadrootsNostrExternalSigningRequest {
+#[cfg(feature = "events")]
+pub struct ExternalSigningRequest {
unsigned_event: nostr::UnsignedEvent,
expected_event_id: RadrootsNostrEventId,
expected_public_key: RadrootsNostrPublicKey,
}
-impl RadrootsNostrExternalSigningRequest {
+#[cfg(feature = "events")]
+impl ExternalSigningRequest {
pub fn expected_event_id(&self) -> RadrootsNostrEventId {
self.expected_event_id
}
@@ -64,39 +66,32 @@ impl RadrootsNostrExternalSigningRequest {
/// Accepts an external signing result only when it is the exact requested
/// event and its NIP-01 identifier and signature are valid.
#[cfg(feature = "std")]
- pub fn complete(
- self,
- event: RadrootsNostrEvent,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn complete(self, event: RadrootsNostrEvent) -> Result<RadrootsNostrEvent, Error> {
if event.pubkey != self.expected_public_key {
- return Err(RadrootsNostrError::ExternalSigningAuthorMismatch {
+ return Err(Error::ExternalSigningAuthorMismatch {
expected: self.expected_public_key,
actual: event.pubkey,
});
}
if event.id != self.expected_event_id {
- return Err(RadrootsNostrError::ExternalSigningEventIdMismatch {
+ return Err(Error::ExternalSigningEventIdMismatch {
expected: self.expected_event_id,
actual: event.id,
});
}
- event
- .verify()
- .map_err(RadrootsNostrError::ExternalSigningEventInvalid)?;
+ event.verify().map_err(Error::ExternalSigningEventInvalid)?;
Ok(event)
}
#[cfg(feature = "std")]
- fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
let event = self.unsigned_event.clone().sign_with_keys(keys)?;
self.complete(event)
}
}
-impl serde::Serialize for RadrootsNostrExternalSigningRequest {
+#[cfg(feature = "events")]
+impl serde::Serialize for ExternalSigningRequest {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@@ -117,45 +112,44 @@ impl serde::Serialize for RadrootsNostrExternalSigningRequest {
/// The upstream unsigned builder is intentionally inaccessible:
///
/// ```compile_fail
-/// use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-/// use radroots_nostr::event::Kind as RadrootsNostrKind;
+/// use radroots_nostr::event::{GenericBuilder, Kind};
///
-/// let builder = RadrootsNostrGenericEventBuilder::new(
-/// RadrootsNostrKind::Custom(30_001),
+/// let builder = GenericBuilder::new(
+/// Kind::Custom(30_001),
/// "content",
/// );
/// let _: nostr::EventBuilder = builder.into();
/// ```
///
/// ```compile_fail
-/// use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-/// use radroots_nostr::event::Kind as RadrootsNostrKind;
+/// use radroots_nostr::event::{GenericBuilder, Kind};
///
-/// let builder = RadrootsNostrGenericEventBuilder::new(
-/// RadrootsNostrKind::Custom(30_001),
+/// let builder = GenericBuilder::new(
+/// Kind::Custom(30_001),
/// "content",
/// );
/// let _raw: nostr::EventBuilder = builder.into_inner();
/// ```
///
/// ```compile_fail
-/// use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-/// use radroots_nostr::types::RadrootsNostrKeys;
-/// use radroots_nostr::event::Kind as RadrootsNostrKind;
+/// use nostr::Keys;
+/// use radroots_nostr::event::{GenericBuilder, Kind};
///
-/// let builder = RadrootsNostrGenericEventBuilder::new(
-/// RadrootsNostrKind::Custom(30_001),
+/// let builder = GenericBuilder::new(
+/// Kind::Custom(30_001),
/// "content",
/// );
-/// let keys = RadrootsNostrKeys::generate();
+/// let keys = Keys::generate();
/// let _unsigned = builder.build(keys.public_key());
/// ```
#[must_use = "generic event builders must be signed or published"]
-pub struct RadrootsNostrGenericEventBuilder {
+#[cfg(feature = "events")]
+pub struct GenericBuilder {
inner: RadrootsNostrEventBuilderUnchecked,
}
-impl RadrootsNostrGenericEventBuilder {
+#[cfg(feature = "events")]
+impl GenericBuilder {
pub fn new(kind: RadrootsNostrKind, content: impl Into<alloc::string::String>) -> Self {
Self::from_unchecked(RadrootsNostrEventBuilderUnchecked::new(kind, content))
}
@@ -199,10 +193,7 @@ impl RadrootsNostrGenericEventBuilder {
/// Signs a generic event after enforcing typed-authoring reservations.
#[cfg(feature = "std")]
- pub fn sign_with_keys(
- self,
- keys: &RadrootsNostrKeys,
- ) -> Result<RadrootsNostrEvent, RadrootsNostrError> {
+ pub fn sign_with_keys(self, keys: &RadrootsNostrKeys) -> Result<RadrootsNostrEvent, Error> {
self.into_external_signing_request(keys.public_key())?
.sign_with_keys(keys)
}
@@ -213,11 +204,11 @@ impl RadrootsNostrGenericEventBuilder {
pub fn into_external_signing_request(
self,
public_key: RadrootsNostrPublicKey,
- ) -> Result<RadrootsNostrExternalSigningRequest, RadrootsNostrError> {
+ ) -> Result<ExternalSigningRequest, Error> {
self.validate_generic_authoring_policy()?;
let mut unsigned_event = self.inner.build(public_key);
let expected_event_id = unsigned_event.id();
- Ok(RadrootsNostrExternalSigningRequest {
+ Ok(ExternalSigningRequest {
unsigned_event,
expected_event_id,
expected_public_key: public_key,
@@ -229,7 +220,7 @@ impl RadrootsNostrGenericEventBuilder {
}
#[cfg(feature = "std")]
- fn validate_generic_authoring_policy(&self) -> Result<(), RadrootsNostrError> {
+ fn validate_generic_authoring_policy(&self) -> Result<(), Error> {
// Inspect an unsigned clone so rejection never consults a signer. PoW
// is irrelevant to kind/tag policy and must not delay the check.
let mut inspection = self.inner.clone();
@@ -269,18 +260,13 @@ impl RadrootsNostrGenericEventBuilder {
|| is_reserved_comment
|| is_reserved_focused_listing
{
- return Err(RadrootsNostrError::TypedAuthoringRequired { kind });
+ return Err(Error::TypedAuthoringRequired { kind });
}
Ok(())
}
}
-pub use nostr::nips::nip19::{
- FromBech32 as RadrootsNostrFromBech32, ToBech32 as RadrootsNostrToBech32,
-};
-pub use nostr::secp256k1::SecretKey as RadrootsNostrSecp256k1SecretKey;
-
-#[cfg(test)]
+#[cfg(all(test, feature = "events"))]
mod tests {
use super::*;
@@ -294,15 +280,15 @@ mod tests {
for (builder, expected_kind) in [
(
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Metadata, "{}"),
+ GenericBuilder::new(RadrootsNostrKind::Metadata, "{}"),
RadrootsNostrKind::Metadata.as_u16(),
),
(
- RadrootsNostrGenericEventBuilder::text_note("root post"),
+ GenericBuilder::text_note("root post"),
RadrootsNostrKind::TextNote.as_u16(),
),
(
- RadrootsNostrGenericEventBuilder::new(
+ GenericBuilder::new(
RadrootsNostrKind::Custom(
radroots_event::envelope::kind::KIND_DELETION_REQUEST as u16,
),
@@ -311,7 +297,7 @@ mod tests {
radroots_event::envelope::kind::KIND_DELETION_REQUEST as u16,
),
(
- RadrootsNostrGenericEventBuilder::new(
+ GenericBuilder::new(
RadrootsNostrKind::Custom(radroots_event::envelope::kind::KIND_COMMENT as u16),
"Comment",
),
@@ -320,7 +306,7 @@ mod tests {
] {
assert!(matches!(
builder.sign_with_keys(&keys),
- Err(RadrootsNostrError::TypedAuthoringRequired { kind })
+ Err(Error::TypedAuthoringRequired { kind })
if kind == expected_kind
));
}
@@ -328,24 +314,23 @@ mod tests {
#[test]
fn generic_direct_signing_rejects_thread_kind_one() {
- let error = RadrootsNostrGenericEventBuilder::text_note("reply")
+ let error = GenericBuilder::text_note("reply")
.tag(RadrootsNostrTag::event(RadrootsNostrEventId::all_zeros()))
.sign_with_keys(&keys())
.expect_err("all kind-1 authoring is typed");
assert!(matches!(
error,
- RadrootsNostrError::TypedAuthoringRequired { kind }
+ Error::TypedAuthoringRequired { kind }
if kind == RadrootsNostrKind::TextNote.as_u16()
));
}
#[test]
fn generic_direct_signing_allows_non_reserved_kind() {
- let event =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(30_001), "generic")
- .sign_with_keys(&keys())
- .expect("generic kind signs");
+ let event = GenericBuilder::new(RadrootsNostrKind::Custom(30_001), "generic")
+ .sign_with_keys(&keys())
+ .expect("generic kind signs");
assert_eq!(event.kind.as_u16(), 30_001);
}
@@ -353,11 +338,10 @@ mod tests {
#[test]
fn external_signing_request_serializes_as_canonical_unsigned_event() {
let keys = keys();
- let request =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .into_external_signing_request(keys.public_key())
- .expect("checked request");
+ let request = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .into_external_signing_request(keys.public_key())
+ .expect("checked request");
let expected_event_id = request.expected_event_id();
let encoded = serde_json::to_vec(&request).expect("serialize request");
@@ -374,7 +358,7 @@ mod tests {
#[test]
fn external_signing_request_rejects_reserved_authoring_before_finalization() {
- let error = match RadrootsNostrGenericEventBuilder::text_note("reserved")
+ let error = match GenericBuilder::text_note("reserved")
.into_external_signing_request(keys().public_key())
{
Ok(_) => panic!("kind 1 remains typed-only"),
@@ -383,7 +367,7 @@ mod tests {
assert!(matches!(
error,
- RadrootsNostrError::TypedAuthoringRequired { kind }
+ Error::TypedAuthoringRequired { kind }
if kind == RadrootsNostrKind::TextNote.as_u16()
));
}
@@ -391,11 +375,10 @@ mod tests {
#[test]
fn external_signing_request_accepts_only_the_exact_valid_event() {
let keys = keys();
- let request =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .into_external_signing_request(keys.public_key())
- .expect("checked request");
+ let request = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .into_external_signing_request(keys.public_key())
+ .expect("checked request");
let unsigned_event: nostr::UnsignedEvent =
serde_json::from_value(serde_json::to_value(&request).expect("request value"))
.expect("unsigned event");
@@ -403,28 +386,25 @@ mod tests {
.sign_with_keys(&keys)
.expect("valid signing result");
- let wrong_author =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .sign_with_keys(&RadrootsNostrKeys::generate())
- .expect("other author event");
+ let wrong_author = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .sign_with_keys(&RadrootsNostrKeys::generate())
+ .expect("other author event");
assert!(matches!(
request.complete(wrong_author),
- Err(RadrootsNostrError::ExternalSigningAuthorMismatch { .. })
+ Err(Error::ExternalSigningAuthorMismatch { .. })
));
- let request =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .into_external_signing_request(keys.public_key())
- .expect("checked request");
- let wrong_event_id =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "different")
- .sign_with_keys(&keys)
- .expect("different event");
+ let request = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .into_external_signing_request(keys.public_key())
+ .expect("checked request");
+ let wrong_event_id = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "different")
+ .sign_with_keys(&keys)
+ .expect("different event");
assert!(matches!(
request.complete(wrong_event_id),
- Err(RadrootsNostrError::ExternalSigningEventIdMismatch { .. })
+ Err(Error::ExternalSigningEventIdMismatch { .. })
));
for mutate in [
@@ -439,36 +419,31 @@ mod tests {
)]);
},
] {
- let request = RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(24_133),
- "protocol",
- )
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .into_external_signing_request(keys.public_key())
- .expect("checked request");
+ let request = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .into_external_signing_request(keys.public_key())
+ .expect("checked request");
let mut tampered = valid_event.clone();
mutate(&mut tampered);
assert!(matches!(
request.complete(tampered),
- Err(RadrootsNostrError::ExternalSigningEventInvalid(_))
+ Err(Error::ExternalSigningEventInvalid(_))
));
}
- let other_signature =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "different")
- .sign_with_keys(&keys)
- .expect("other event")
- .sig;
- let request =
- RadrootsNostrGenericEventBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
- .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
- .into_external_signing_request(keys.public_key())
- .expect("checked request");
+ let other_signature = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "different")
+ .sign_with_keys(&keys)
+ .expect("other event")
+ .sig;
+ let request = GenericBuilder::new(RadrootsNostrKind::Custom(24_133), "protocol")
+ .custom_created_at(RadrootsNostrTimestamp::from_secs(1_234))
+ .into_external_signing_request(keys.public_key())
+ .expect("checked request");
let mut invalid_signature = valid_event;
invalid_signature.sig = other_signature;
assert!(matches!(
request.complete(invalid_signature),
- Err(RadrootsNostrError::ExternalSigningEventInvalid(_))
+ Err(Error::ExternalSigningEventInvalid(_))
));
}
}
diff --git a/crates/nostr/tests/blossom_conformance.rs b/crates/nostr/tests/blossom_conformance.rs
@@ -1,6 +1,7 @@
#![cfg(feature = "blossom")]
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
+use nostr::Keys as RadrootsNostrKeys;
use radroots_blossom::{
Sha256,
authorization::{
@@ -11,15 +12,14 @@ use radroots_blossom::{
},
};
use radroots_nostr::blossom::{
- RadrootsNostrBlossomError, radroots_nostr_decode_verify_blossom_authorization_header,
- radroots_nostr_encode_blossom_authorization_header, radroots_nostr_sign_blossom_authorization,
+ AuthorizationError, decode_verify_authorization_header, encode_authorization_header,
+ sign_authorization,
};
use radroots_nostr::{
event::{
Event as RadrootsNostrEvent, Kind as RadrootsNostrKind, Timestamp as RadrootsNostrTimestamp,
},
tag::Tag as RadrootsNostrTag,
- types::RadrootsNostrKeys,
};
use serde::Deserialize;
use serde_json::Value;
@@ -94,11 +94,9 @@ fn execute_vector(vector: &Vector) {
let validation = vector_validation(vector);
match vector.kind.as_str() {
"blossom.bud11.nostr.decode_verify.valid" => {
- let verified = radroots_nostr_decode_verify_blossom_authorization_header(
- input_str(vector, "header"),
- &validation,
- )
- .unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
+ let verified =
+ decode_verify_authorization_header(input_str(vector, "header"), &validation)
+ .unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
assert_eq!(
verified.event_id().to_string(),
expected_str(vector, "event_id"),
@@ -159,16 +157,14 @@ fn execute_vector(vector: &Vector) {
);
}
"blossom.bud11.nostr.decode_verify.invalid" => {
- let error = radroots_nostr_decode_verify_blossom_authorization_header(
- input_str(vector, "header"),
- &validation,
- )
- .expect_err("invalid BUD-11 Nostr vector must fail");
+ let error =
+ decode_verify_authorization_header(input_str(vector, "header"), &validation)
+ .expect_err("invalid BUD-11 Nostr vector must fail");
assert_eq!(error.code(), expected_str(vector, "error"), "{}", vector.id);
if let Some(actual_kind) = vector.expected.get("actual_kind") {
assert_eq!(
error,
- RadrootsNostrBlossomError::InvalidEventKind {
+ AuthorizationError::InvalidEventKind {
actual: actual_kind.as_u64().expect("actual_kind must be u64"),
},
"{}",
@@ -366,11 +362,10 @@ fn sign_raw(kind: u16, content: &str, tags: Vec<RadrootsNostrTag>) -> RadrootsNo
#[test]
fn blossom_authored_claim_signs_and_roundtrips_without_signature_assumptions() {
let claim = authored_claim();
- let signed = radroots_nostr_sign_blossom_authorization(&keys(), &claim)
- .expect("sign authored authorization");
+ let signed = sign_authorization(&keys(), &claim).expect("sign authored authorization");
let wire = claim.wire_parts();
- let header = radroots_nostr_encode_blossom_authorization_header(&signed);
+ let header = encode_authorization_header(&signed);
let event = event_from_header(header.as_str());
assert_eq!(event.kind.as_u16(), wire.kind());
@@ -397,8 +392,7 @@ fn blossom_authored_claim_signs_and_roundtrips_without_signature_assumptions() {
assert!(!format!("{signed:?}").contains(&event.sig.to_string()));
let verified =
- radroots_nostr_decode_verify_blossom_authorization_header(header.as_str(), &validation())
- .expect("verify header");
+ decode_verify_authorization_header(header.as_str(), &validation()).expect("verify header");
assert_eq!(verified.event_id(), event.id);
assert_eq!(verified.author(), keys().public_key());
assert_eq!(verified.created_at(), event.created_at);
@@ -413,61 +407,49 @@ fn blossom_authored_claim_signs_and_roundtrips_without_signature_assumptions() {
#[test]
fn blossom_header_rejects_noncanonical_and_malformed_encodings() {
- let signed = radroots_nostr_sign_blossom_authorization(&keys(), &authored_claim())
- .expect("sign authored authorization");
- let valid = radroots_nostr_encode_blossom_authorization_header(&signed).into_string();
+ let signed =
+ sign_authorization(&keys(), &authored_claim()).expect("sign authored authorization");
+ let valid = encode_authorization_header(&signed).into_string();
let policy = validation();
for accepted in [
valid.replacen("Nostr ", "nostr ", 1),
valid.replacen("Nostr ", "NOSTR ", 1),
] {
- radroots_nostr_decode_verify_blossom_authorization_header(&accepted, &policy)
+ decode_verify_authorization_header(&accepted, &policy)
.expect("auth-scheme is case-insensitive and accepts 1*SP");
}
let cases = [
(
format!(" {valid}"),
- RadrootsNostrBlossomError::InvalidHeaderWhitespace,
+ AuthorizationError::InvalidHeaderWhitespace,
),
(
"Nostr e 30".to_owned(),
- RadrootsNostrBlossomError::InvalidHeaderWhitespace,
- ),
- (
- "Nostr".to_owned(),
- RadrootsNostrBlossomError::InvalidHeaderScheme,
- ),
- (
- "Nostr ".to_owned(),
- RadrootsNostrBlossomError::EmptyHeaderPayload,
+ AuthorizationError::InvalidHeaderWhitespace,
),
+ ("Nostr".to_owned(), AuthorizationError::InvalidHeaderScheme),
+ ("Nostr ".to_owned(), AuthorizationError::EmptyHeaderPayload),
(
format!("{valid}="),
- RadrootsNostrBlossomError::HeaderPaddingForbidden,
+ AuthorizationError::HeaderPaddingForbidden,
),
(
"Nostr +".to_owned(),
- RadrootsNostrBlossomError::InvalidHeaderBase64,
+ AuthorizationError::InvalidHeaderBase64,
),
(
"Nostr Zh".to_owned(),
- RadrootsNostrBlossomError::NonCanonicalHeaderBase64,
- ),
- (
- "Nostr _w".to_owned(),
- RadrootsNostrBlossomError::InvalidHeaderUtf8,
- ),
- (
- "Nostr e30".to_owned(),
- RadrootsNostrBlossomError::InvalidEventJson,
+ AuthorizationError::NonCanonicalHeaderBase64,
),
+ ("Nostr _w".to_owned(), AuthorizationError::InvalidHeaderUtf8),
+ ("Nostr e30".to_owned(), AuthorizationError::InvalidEventJson),
];
for (header, expected) in cases {
assert_eq!(
- radroots_nostr_decode_verify_blossom_authorization_header(&header, &policy),
+ decode_verify_authorization_header(&header, &policy),
Err(expected),
"{header}"
);
@@ -476,9 +458,9 @@ fn blossom_header_rejects_noncanonical_and_malformed_encodings() {
#[test]
fn blossom_header_rejects_kind_narrowing_and_json_shape_laundering() {
- let signed = radroots_nostr_sign_blossom_authorization(&keys(), &authored_claim())
- .expect("sign authored authorization");
- let encoded = radroots_nostr_encode_blossom_authorization_header(&signed);
+ let signed =
+ sign_authorization(&keys(), &authored_claim()).expect("sign authored authorization");
+ let encoded = encode_authorization_header(&signed);
let event_json =
serde_json::to_string(&event_from_header(encoded.as_str())).expect("event JSON");
let policy = validation();
@@ -486,37 +468,34 @@ fn blossom_header_rejects_kind_narrowing_and_json_shape_laundering() {
let cases = [
(
event_json.replacen("\"kind\":24242", "\"kind\":89778", 1),
- RadrootsNostrBlossomError::InvalidEventKind { actual: 89_778 },
+ AuthorizationError::InvalidEventKind { actual: 89_778 },
),
(
format!(
"{},\"unknown\":true}}",
event_json.strip_suffix('}').unwrap()
),
- RadrootsNostrBlossomError::InvalidEventJson,
+ AuthorizationError::InvalidEventJson,
),
(
event_json.replacen("\"content\":", "\"unknown\":", 1),
- RadrootsNostrBlossomError::InvalidEventJson,
+ AuthorizationError::InvalidEventJson,
),
(
event_json.replacen("\"kind\":24242", "\"kind\":24242,\"kind\":24242", 1),
- RadrootsNostrBlossomError::InvalidEventJson,
+ AuthorizationError::InvalidEventJson,
),
(
event_json.replacen("\"kind\":24242", "\"kind\":\"24242\"", 1),
- RadrootsNostrBlossomError::InvalidEventJson,
+ AuthorizationError::InvalidEventJson,
),
- ("[]".to_owned(), RadrootsNostrBlossomError::InvalidEventJson),
- ("{".to_owned(), RadrootsNostrBlossomError::InvalidEventJson),
+ ("[]".to_owned(), AuthorizationError::InvalidEventJson),
+ ("{".to_owned(), AuthorizationError::InvalidEventJson),
];
for (json, expected) in cases {
assert_eq!(
- radroots_nostr_decode_verify_blossom_authorization_header(
- &raw_json_header(&json),
- &policy,
- ),
+ decode_verify_authorization_header(&raw_json_header(&json), &policy,),
Err(expected),
"{json}"
);
@@ -529,19 +508,16 @@ fn blossom_header_authenticates_before_claim_parsing() {
let wrong_kind = sign_raw(1, "", Vec::new());
assert_eq!(
- radroots_nostr_decode_verify_blossom_authorization_header(
- &raw_header(&wrong_kind),
- &policy
- ),
- Err(RadrootsNostrBlossomError::InvalidEventKind { actual: 1 })
+ decode_verify_authorization_header(&raw_header(&wrong_kind), &policy),
+ Err(AuthorizationError::InvalidEventKind { actual: 1 })
);
let malformed_claim = sign_raw(RADROOTS_BLOSSOM_AUTHORIZATION_EVENT_KIND, "", Vec::new());
let mut bad_id = malformed_claim.clone();
bad_id.content.push('x');
assert_eq!(
- radroots_nostr_decode_verify_blossom_authorization_header(&raw_header(&bad_id), &policy),
- Err(RadrootsNostrBlossomError::InvalidEventId)
+ decode_verify_authorization_header(&raw_header(&bad_id), &policy),
+ Err(AuthorizationError::InvalidEventId)
);
let mut bad_signature = malformed_claim.clone();
@@ -554,27 +530,21 @@ fn blossom_header_authenticates_before_claim_parsing() {
assert!(bad_signature.verify_id());
assert!(!bad_signature.verify_signature());
assert_eq!(
- radroots_nostr_decode_verify_blossom_authorization_header(
- &raw_header(&bad_signature),
- &policy
- ),
- Err(RadrootsNostrBlossomError::InvalidEventSignature)
+ decode_verify_authorization_header(&raw_header(&bad_signature), &policy),
+ Err(AuthorizationError::InvalidEventSignature)
);
let raw_tags: Vec<Vec<String>> = Vec::new();
let pure_error = AuthorizationClaim::parse("", CREATED_AT, &raw_tags)
.expect_err("empty content is not a claim");
- let adapter_error = radroots_nostr_decode_verify_blossom_authorization_header(
- &raw_header(&malformed_claim),
- &policy,
- )
- .expect_err("authenticated malformed claim must fail");
+ let adapter_error = decode_verify_authorization_header(&raw_header(&malformed_claim), &policy)
+ .expect_err("authenticated malformed claim must fail");
assert_eq!(adapter_error.code(), pure_error.code());
assert_eq!(adapter_error.blossom_claim_error(), Some(&pure_error));
assert_eq!(adapter_error.to_string(), pure_error.to_string());
- let signed = radroots_nostr_sign_blossom_authorization(&keys(), &authored_claim())
- .expect("sign authored authorization");
+ let signed =
+ sign_authorization(&keys(), &authored_claim()).expect("sign authored authorization");
let media_policy = AuthorizationValidation::new(
AuthorizationTarget::Media(hash()),
server(),
@@ -583,8 +553,8 @@ fn blossom_header_authenticates_before_claim_parsing() {
RADROOTS_BLOSSOM_AUTH_MAX_CREATED_AGE_SECONDS,
)
.expect("media validation policy");
- let validation_error = radroots_nostr_decode_verify_blossom_authorization_header(
- radroots_nostr_encode_blossom_authorization_header(&signed).as_str(),
+ let validation_error = decode_verify_authorization_header(
+ encode_authorization_header(&signed).as_str(),
&media_policy,
)
.expect_err("upload claim must not authorize media endpoint");
@@ -594,22 +564,22 @@ fn blossom_header_authenticates_before_claim_parsing() {
#[test]
fn blossom_adapter_error_codes_are_stable_and_distinct() {
let errors = [
- RadrootsNostrBlossomError::InvalidHeaderWhitespace,
- RadrootsNostrBlossomError::InvalidHeaderScheme,
- RadrootsNostrBlossomError::EmptyHeaderPayload,
- RadrootsNostrBlossomError::HeaderPaddingForbidden,
- RadrootsNostrBlossomError::InvalidHeaderBase64,
- RadrootsNostrBlossomError::NonCanonicalHeaderBase64,
- RadrootsNostrBlossomError::InvalidHeaderUtf8,
- RadrootsNostrBlossomError::InvalidEventJson,
- RadrootsNostrBlossomError::InvalidEventKind { actual: 1 },
- RadrootsNostrBlossomError::InvalidEventId,
- RadrootsNostrBlossomError::InvalidEventSignature,
- RadrootsNostrBlossomError::EventSigning,
+ AuthorizationError::InvalidHeaderWhitespace,
+ AuthorizationError::InvalidHeaderScheme,
+ AuthorizationError::EmptyHeaderPayload,
+ AuthorizationError::HeaderPaddingForbidden,
+ AuthorizationError::InvalidHeaderBase64,
+ AuthorizationError::NonCanonicalHeaderBase64,
+ AuthorizationError::InvalidHeaderUtf8,
+ AuthorizationError::InvalidEventJson,
+ AuthorizationError::InvalidEventKind { actual: 1 },
+ AuthorizationError::InvalidEventId,
+ AuthorizationError::InvalidEventSignature,
+ AuthorizationError::EventSigning,
];
let mut codes = errors
.iter()
- .map(RadrootsNostrBlossomError::code)
+ .map(AuthorizationError::code)
.collect::<Vec<_>>();
let before = codes.len();
codes.sort_unstable();
diff --git a/crates/nostr/tests/coverage.rs b/crates/nostr/tests/coverage.rs
@@ -3,33 +3,28 @@ mod test_fixtures;
use std::borrow::Cow;
-use nostr::nips::nip04;
+use nostr::{Keys as RadrootsNostrKeys, RelayUrl as RadrootsNostrRelayUrl, nips::nip04};
#[cfg(feature = "events")]
use radroots_event::post::reply::{AuthoredNip10Reply, Nip10ReplyReference};
-use radroots_nostr::error::RadrootsNostrTagsResolveError;
-use radroots_nostr::events::jobs::{
- radroots_nostr_build_event_job_feedback, radroots_nostr_build_event_job_result,
-};
-use radroots_nostr::events::post::radroots_nostr_post_events_filter;
#[cfg(feature = "events")]
-use radroots_nostr::events::reply::radroots_nostr_build_nip10_reply_event;
+use radroots_nostr::event::build_nip10_reply as build_nip10_reply_event;
+use radroots_nostr::event::{Kind as RadrootsNostrKind, Timestamp as RadrootsNostrTimestamp};
+use radroots_nostr::event::{
+ build_job_feedback as build_event_job_feedback, build_job_result as build_event_job_result,
+ created_at_u32_saturating, event_created_at_u32_saturating, post_filter as post_events_filter,
+};
use radroots_nostr::filter::{
- radroots_nostr_filter_kind, radroots_nostr_filter_new_events, radroots_nostr_filter_tag,
- radroots_nostr_kind,
+ for_kind as filter_kind, kind, since_now as filter_new_events, with_tag as filter_tag,
};
use radroots_nostr::key::{parse_public_key, public_key_from_nostr, public_key_to_npub};
use radroots_nostr::tag::{
- Tag as RadrootsNostrTag, TagKind as RadrootsNostrTagKind,
- TagStandard as RadrootsNostrTagStandard, radroots_nostr_tag_at_value,
- radroots_nostr_tag_first_value, radroots_nostr_tag_match_geohash, radroots_nostr_tag_match_l,
- radroots_nostr_tag_match_location, radroots_nostr_tag_match_summary,
- radroots_nostr_tag_match_title, radroots_nostr_tag_relays_parse, radroots_nostr_tag_slice,
- radroots_nostr_tags_match, radroots_nostr_tags_resolve,
-};
-use radroots_nostr::util::{created_at_u32_saturating, event_created_at_u32_saturating};
-use radroots_nostr::{
- event::{Kind as RadrootsNostrKind, Timestamp as RadrootsNostrTimestamp},
- types::{RadrootsNostrKeys, RadrootsNostrRelayUrl},
+ ResolveError, Tag as RadrootsNostrTag, TagKind as RadrootsNostrTagKind,
+ TagStandard as RadrootsNostrTagStandard, first_value as tag_first_value,
+ match_geohash as tag_match_geohash, match_location as tag_match_location,
+ match_location_coordinate as tag_match_l, match_parts as tags_match,
+ match_summary as tag_match_summary, match_title as tag_match_title,
+ relay_urls as tag_relays_parse, resolve as tags_resolve, value_at as tag_at_value,
+ values_from as tag_slice,
};
use test_fixtures::RELAY_PRIMARY_WSS;
@@ -71,7 +66,7 @@ fn job_event_builders_are_callable() {
.sign_with_keys(&keys)
.expect("non-job request");
- let job_result = radroots_nostr_build_event_job_result(
+ let job_result = build_event_job_result(
&job_request,
"ok",
1,
@@ -83,7 +78,7 @@ fn job_event_builders_are_callable() {
.sign_with_keys(&keys)
.expect("job result signs through the generic boundary");
- let feedback_ok = radroots_nostr_build_event_job_feedback(
+ let feedback_ok = build_event_job_feedback(
&job_request,
"success",
Some("extra".to_string()),
@@ -94,14 +89,13 @@ fn job_event_builders_are_callable() {
.sign_with_keys(&keys)
.expect("job feedback signs through the generic boundary");
- let feedback_invalid =
- radroots_nostr_build_event_job_feedback(&job_request, "invalid-status", None, None)
- .expect("job feedback fallback builder");
+ let feedback_invalid = build_event_job_feedback(&job_request, "invalid-status", None, None)
+ .expect("job feedback fallback builder");
let _ = feedback_invalid
.sign_with_keys(&keys)
.expect("fallback job feedback signs through the generic boundary");
- let invalid_job_result = radroots_nostr_build_event_job_result(
+ let invalid_job_result = build_event_job_result(
&non_job_request,
"ok",
1,
@@ -113,8 +107,8 @@ fn job_event_builders_are_callable() {
#[test]
fn post_helpers_cover_success_and_error_paths() {
- let _ = radroots_nostr_post_events_filter(None, None);
- let _ = radroots_nostr_post_events_filter(Some(10), Some(1_700_000_000));
+ let _ = post_events_filter(None, None);
+ let _ = post_events_filter(Some(10), Some(1_700_000_000));
#[cfg(feature = "events")]
{
@@ -132,8 +126,7 @@ fn post_helpers_cover_success_and_error_paths() {
.expect("root reference");
let direct = AuthoredNip10Reply::direct("direct reply", root_reference.clone())
.expect("direct reply");
- let direct_builder =
- radroots_nostr_build_nip10_reply_event(&direct).expect("direct reply builder");
+ let direct_builder = build_nip10_reply_event(&direct).expect("direct reply builder");
let _ = direct_builder
.sign_with_keys(&keys)
.expect("direct reply signs through the typed boundary");
@@ -142,8 +135,7 @@ fn post_helpers_cover_success_and_error_paths() {
.expect("parent reference");
let nested = AuthoredNip10Reply::nested("nested reply", root_reference, parent_reference)
.expect("nested reply");
- let nested_builder =
- radroots_nostr_build_nip10_reply_event(&nested).expect("nested reply builder");
+ let nested_builder = build_nip10_reply_event(&nested).expect("nested reply builder");
let _ = nested_builder
.sign_with_keys(&keys)
.expect("nested reply signs through the typed boundary");
@@ -164,24 +156,21 @@ fn post_helpers_cover_success_and_error_paths() {
#[test]
fn filter_helpers_cover_all_paths() {
- let filter = radroots_nostr_filter_kind(1);
- let filtered = radroots_nostr_filter_tag(filter, "p", vec!["x".to_string()]);
+ let filter = filter_kind(1);
+ let filtered = filter_tag(filter, "p", vec!["x".to_string()]);
assert!(filtered.is_ok());
- let empty_tag =
- radroots_nostr_filter_tag(radroots_nostr_filter_kind(1), "", vec!["x".to_string()]);
+ let empty_tag = filter_tag(filter_kind(1), "", vec!["x".to_string()]);
assert!(empty_tag.is_err());
- let multi_tag =
- radroots_nostr_filter_tag(radroots_nostr_filter_kind(1), "pp", vec!["x".to_string()]);
+ let multi_tag = filter_tag(filter_kind(1), "pp", vec!["x".to_string()]);
assert!(multi_tag.is_err());
- let invalid_tag =
- radroots_nostr_filter_tag(radroots_nostr_filter_kind(1), "1", vec!["x".to_string()]);
+ let invalid_tag = filter_tag(filter_kind(1), "1", vec!["x".to_string()]);
assert!(invalid_tag.is_err());
- let _ = radroots_nostr_kind(30000);
- let _ = radroots_nostr_filter_new_events(radroots_nostr_filter_kind(1));
+ let _ = kind(30000);
+ let _ = filter_new_events(filter_kind(1));
}
#[test]
@@ -207,50 +196,44 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
RadrootsNostrTagKind::Custom(Cow::Borrowed("x")),
vec!["v1".to_string(), "v2".to_string()],
);
+ assert_eq!(tag_first_value(&custom_tag, "x"), Some("v1".to_string()));
+ assert_eq!(tag_first_value(&custom_tag, "y"), None);
+ assert_eq!(tag_at_value(&custom_tag, 0), Some("x".to_string()));
+ assert_eq!(tag_at_value(&custom_tag, 9), None);
assert_eq!(
- radroots_nostr_tag_first_value(&custom_tag, "x"),
- Some("v1".to_string())
- );
- assert_eq!(radroots_nostr_tag_first_value(&custom_tag, "y"), None);
- assert_eq!(
- radroots_nostr_tag_at_value(&custom_tag, 0),
- Some("x".to_string())
- );
- assert_eq!(radroots_nostr_tag_at_value(&custom_tag, 9), None);
- assert_eq!(
- radroots_nostr_tag_slice(&custom_tag, 1),
+ tag_slice(&custom_tag, 1),
Some(vec!["v1".to_string(), "v2".to_string()])
);
- assert_eq!(radroots_nostr_tag_slice(&custom_tag, 9), None);
- let matched = radroots_nostr_tags_match(&custom_tag).expect("custom match");
+ assert_eq!(tag_slice(&custom_tag, 9), None);
+ let matched = tags_match(&custom_tag).expect("custom match");
assert_eq!(matched.0, "x");
assert_eq!(matched.1, ["v1".to_string(), "v2".to_string()]);
let relays_tag = RadrootsNostrTag::from_standardized(RadrootsNostrTagStandard::Relays(vec![
RadrootsNostrRelayUrl::parse(RELAY_PRIMARY_WSS).expect("relay"),
]));
- assert!(radroots_nostr_tag_relays_parse(&relays_tag).is_some());
+ assert!(tag_relays_parse(&relays_tag).is_some());
let relays_non_match =
RadrootsNostrTag::from_standardized(RadrootsNostrTagStandard::Title("x".to_string()));
- assert!(radroots_nostr_tag_relays_parse(&relays_non_match).is_none());
- assert!(radroots_nostr_tag_relays_parse(&custom_tag).is_none());
+ assert!(tag_relays_parse(&relays_non_match).is_none());
+ assert!(tag_relays_parse(&custom_tag).is_none());
let l_tag = RadrootsNostrTag::custom(
RadrootsNostrTagKind::Custom(Cow::Borrowed("l")),
vec!["12.5".to_string(), "kg".to_string()],
);
- assert_eq!(radroots_nostr_tag_match_l(&l_tag), Some(("kg", 12.5)));
+ assert_eq!(tag_match_l(&l_tag), Some(("kg", 12.5)));
let bad_l_tag = RadrootsNostrTag::custom(
RadrootsNostrTagKind::Custom(Cow::Borrowed("l")),
vec!["abc".to_string(), "kg".to_string()],
);
- assert_eq!(radroots_nostr_tag_match_l(&bad_l_tag), None);
- assert_eq!(radroots_nostr_tag_match_l(&custom_tag), None);
+ assert_eq!(tag_match_l(&bad_l_tag), None);
+ assert_eq!(tag_match_l(&custom_tag), None);
let short_l_tag = RadrootsNostrTag::custom(
RadrootsNostrTagKind::Custom(Cow::Borrowed("l")),
vec!["12.5".to_string()],
);
- assert_eq!(radroots_nostr_tag_match_l(&short_l_tag), None);
+ assert_eq!(tag_match_l(&short_l_tag), None);
let location_tag = RadrootsNostrTag::custom(
RadrootsNostrTagKind::Custom(Cow::Borrowed("location")),
@@ -261,7 +244,7 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
],
);
assert_eq!(
- radroots_nostr_tag_match_location(&location_tag),
+ tag_match_location(&location_tag),
Some(("se", "stockholm", "city"))
);
let location_non_match = RadrootsNostrTag::custom(
@@ -272,36 +255,27 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
"city".to_string(),
],
);
- assert_eq!(radroots_nostr_tag_match_location(&location_non_match), None);
- assert_eq!(radroots_nostr_tag_match_location(&custom_tag), None);
+ assert_eq!(tag_match_location(&location_non_match), None);
+ assert_eq!(tag_match_location(&custom_tag), None);
let geohash_tag =
RadrootsNostrTag::from_standardized(RadrootsNostrTagStandard::Geohash("u4pr".to_string()));
- assert_eq!(
- radroots_nostr_tag_match_geohash(&geohash_tag),
- Some("u4pr".to_string())
- );
+ assert_eq!(tag_match_geohash(&geohash_tag), Some("u4pr".to_string()));
let title_tag =
RadrootsNostrTag::from_standardized(RadrootsNostrTagStandard::Title("title".to_string()));
- assert_eq!(radroots_nostr_tag_match_geohash(&title_tag), None);
- assert_eq!(radroots_nostr_tag_match_geohash(&custom_tag), None);
+ assert_eq!(tag_match_geohash(&title_tag), None);
+ assert_eq!(tag_match_geohash(&custom_tag), None);
- assert_eq!(
- radroots_nostr_tag_match_title(&title_tag),
- Some("title".to_string())
- );
+ assert_eq!(tag_match_title(&title_tag), Some("title".to_string()));
let summary_tag = RadrootsNostrTag::from_standardized(RadrootsNostrTagStandard::Summary(
"summary".to_string(),
));
- assert_eq!(radroots_nostr_tag_match_title(&summary_tag), None);
- assert_eq!(radroots_nostr_tag_match_title(&custom_tag), None);
+ assert_eq!(tag_match_title(&summary_tag), None);
+ assert_eq!(tag_match_title(&custom_tag), None);
- assert_eq!(
- radroots_nostr_tag_match_summary(&summary_tag),
- Some("summary".to_string())
- );
- assert_eq!(radroots_nostr_tag_match_summary(&geohash_tag), None);
- assert_eq!(radroots_nostr_tag_match_summary(&custom_tag), None);
+ assert_eq!(tag_match_summary(&summary_tag), Some("summary".to_string()));
+ assert_eq!(tag_match_summary(&geohash_tag), None);
+ assert_eq!(tag_match_summary(&custom_tag), None);
let clear_event = text_event_with_tags(
&keys,
@@ -310,7 +284,7 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
vec!["x".to_string(), "v".to_string()],
)],
);
- let resolved = radroots_nostr_tags_resolve(&clear_event, &keys).expect("clear tags");
+ let resolved = tags_resolve(&clear_event, &keys).expect("clear tags");
assert_eq!(resolved.len(), 1);
let encrypted_missing_p = text_event_with_tags(
@@ -320,19 +294,13 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
vec!["encrypted".to_string()],
)],
);
- let missing_p = radroots_nostr_tags_resolve(&encrypted_missing_p, &keys);
- assert!(matches!(
- missing_p,
- Err(RadrootsNostrTagsResolveError::MissingPTag(_))
- ));
+ let missing_p = tags_resolve(&encrypted_missing_p, &keys);
+ assert!(matches!(missing_p, Err(ResolveError::MissingPTag(_))));
let sender = make_keys();
let encrypted_invalid_p = encrypted_event_with_p_tag(&sender, "cipher", "not-a-pubkey");
- let invalid_p = radroots_nostr_tags_resolve(&encrypted_invalid_p, &keys);
- assert!(matches!(
- invalid_p,
- Err(RadrootsNostrTagsResolveError::MissingPTag(_))
- ));
+ let invalid_p = tags_resolve(&encrypted_invalid_p, &keys);
+ assert!(matches!(invalid_p, Err(ResolveError::MissingPTag(_))));
let encrypted_empty_p_content = nostr::EventBuilder::new(RadrootsNostrKind::TextNote, "cipher")
.tags(vec![
@@ -344,45 +312,32 @@ fn tag_helpers_cover_matchers_and_resolve_paths() {
])
.sign_with_keys(&sender)
.expect("sign encrypted event with empty p tag");
- let empty_p_content = radroots_nostr_tags_resolve(&encrypted_empty_p_content, &keys);
- assert!(matches!(
- empty_p_content,
- Err(RadrootsNostrTagsResolveError::MissingPTag(_))
- ));
+ let empty_p_content = tags_resolve(&encrypted_empty_p_content, &keys);
+ assert!(matches!(empty_p_content, Err(ResolveError::MissingPTag(_))));
let encrypted_not_recipient =
encrypted_event_with_p_tag(&sender, "cipher", &other.public_key().to_hex());
- let not_recipient = radroots_nostr_tags_resolve(&encrypted_not_recipient, &keys);
- assert!(matches!(
- not_recipient,
- Err(RadrootsNostrTagsResolveError::NotRecipient)
- ));
+ let not_recipient = tags_resolve(&encrypted_not_recipient, &keys);
+ assert!(matches!(not_recipient, Err(ResolveError::NotRecipient)));
let encrypted_bad_cipher =
encrypted_event_with_p_tag(&sender, "not-ciphertext", &keys.public_key().to_hex());
- let bad_cipher = radroots_nostr_tags_resolve(&encrypted_bad_cipher, &keys);
- assert!(matches!(
- bad_cipher,
- Err(RadrootsNostrTagsResolveError::DecryptionError(_))
- ));
+ let bad_cipher = tags_resolve(&encrypted_bad_cipher, &keys);
+ assert!(matches!(bad_cipher, Err(ResolveError::DecryptionError(_))));
let encrypted_cleartext = nip04::encrypt(sender.secret_key(), &keys.public_key(), "[]")
.expect("encrypt cleartext tags");
let encrypted_ok =
encrypted_event_with_p_tag(&sender, encrypted_cleartext, &keys.public_key().to_hex());
- let resolved_encrypted =
- radroots_nostr_tags_resolve(&encrypted_ok, &keys).expect("resolve tags");
+ let resolved_encrypted = tags_resolve(&encrypted_ok, &keys).expect("resolve tags");
assert!(resolved_encrypted.is_empty());
let encrypted_bad_json = nip04::encrypt(sender.secret_key(), &keys.public_key(), "not-json")
.expect("encrypt invalid tags payload");
let encrypted_bad_json_event =
encrypted_event_with_p_tag(&sender, encrypted_bad_json, &keys.public_key().to_hex());
- let bad_json = radroots_nostr_tags_resolve(&encrypted_bad_json_event, &keys);
- assert!(matches!(
- bad_json,
- Err(RadrootsNostrTagsResolveError::ParseError(_))
- ));
+ let bad_json = tags_resolve(&encrypted_bad_json_event, &keys);
+ assert!(matches!(bad_json, Err(ResolveError::ParseError(_))));
}
#[test]
diff --git a/crates/nostr/tests/food_availability_profile.rs b/crates/nostr/tests/food_availability_profile.rs
@@ -1,3 +1,4 @@
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_blossom::{BlobDescriptor, BlobUrl, MediaType, Sha256};
use radroots_event::food::availability::{
FoodAvailabilityDetails, FoodAvailabilityDetailsParts, FoodAvailabilityImage,
@@ -8,15 +9,13 @@ use radroots_event::media::AuthoredImage;
use radroots_event_codec::admission::food_availability::{
RadrootsFoodAvailabilityAdmissionOutcome, verify_and_admit_food_availability_event,
};
-use radroots_nostr::error::RadrootsNostrError;
+use radroots_nostr::Error;
+use radroots_nostr::event::GenericBuilder;
use radroots_nostr::event::Kind as RadrootsNostrKind;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::event::radroots_event_from_nostr;
-use radroots_nostr::events::food_availability::radroots_nostr_build_food_availability_event;
+use radroots_nostr::event::build_food_availability as build_food_availability_event;
+use radroots_nostr::event::from_nostr;
use radroots_nostr::tag::Tag as RadrootsNostrTag;
-use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-use radroots_nostr::types::RadrootsNostrKeys;
-use radroots_nostr::types::RadrootsNostrSecretKey;
use radroots_test_fixtures::FIXTURE_ALICE_SECRET_KEY_HEX;
const CREATED_AT: u64 = 1_784_347_200;
@@ -25,7 +24,7 @@ const CREATED_AT: u64 = 1_784_347_200;
fn typed_food_builder_signs_the_exact_strict_profile() {
let keys = fixture_keys();
let created_at = RadrootsNostrTimestamp::from_secs(CREATED_AT);
- let event = radroots_nostr_build_food_availability_event(&details(), created_at)
+ let event = build_food_availability_event(&details(), created_at)
.expect("typed FoodAvailability builder")
.sign_with_keys(&keys)
.expect("signed FoodAvailability event");
@@ -58,7 +57,7 @@ fn typed_food_builder_signs_the_exact_strict_profile() {
);
event.verify().expect("valid NIP-01 event");
- let envelope = radroots_event_from_nostr(&event).expect("Radroots event adapter");
+ let envelope = from_nostr(&event).expect("Radroots event adapter");
assert!(matches!(
verify_and_admit_food_availability_event(envelope)
.expect("verified FoodAvailability admission"),
@@ -68,24 +67,19 @@ fn typed_food_builder_signs_the_exact_strict_profile() {
#[test]
fn typed_food_builder_keeps_timestamp_validation_inside_construction() {
- let error = radroots_nostr_build_food_availability_event(
- &details(),
- RadrootsNostrTimestamp::from_secs(1_784_347_000),
- )
- .err()
- .expect("created_at before published_at must fail");
+ let error =
+ build_food_availability_event(&details(), RadrootsNostrTimestamp::from_secs(1_784_347_000))
+ .err()
+ .expect("created_at before published_at must fail");
- assert!(matches!(
- error,
- RadrootsNostrError::FoodAvailabilityEncode(_)
- ));
+ assert!(matches!(error, Error::FoodAvailabilityEncode(_)));
}
#[test]
fn typed_food_builder_preserves_a_byte_verified_blossom_image_tuple() {
let image = blossom_image();
let image_url = image.url().to_owned();
- let event = radroots_nostr_build_food_availability_event(
+ let event = build_food_availability_event(
&details_with_images(vec![image]),
RadrootsNostrTimestamp::from_secs(CREATED_AT),
)
@@ -125,10 +119,10 @@ fn generic_builder_reserves_focused_and_ambiguous_listing_profiles() {
],
] {
assert!(matches!(
- RadrootsNostrGenericEventBuilder::new(kind, "reserved")
+ GenericBuilder::new(kind, "reserved")
.tags(tags)
.sign_with_keys(&keys),
- Err(RadrootsNostrError::TypedAuthoringRequired { kind: 30_402 })
+ Err(Error::TypedAuthoringRequired { kind: 30_402 })
));
}
}
@@ -148,7 +142,7 @@ fn generic_builder_retains_marker_free_and_operational_nip99_compatibility() {
RadrootsNostrTag::parse(["radroots:primary_bin", "bin-1"]).expect("operational marker"),
],
] {
- let event = RadrootsNostrGenericEventBuilder::new(kind, "compatible")
+ let event = GenericBuilder::new(kind, "compatible")
.tags(tags)
.custom_created_at(RadrootsNostrTimestamp::from_secs(CREATED_AT))
.sign_with_keys(&keys)
diff --git a/crates/nostr/tests/generic_builder_boundary.rs b/crates/nostr/tests/generic_builder_boundary.rs
@@ -30,15 +30,15 @@ fn public_source_does_not_expose_the_upstream_event_builder() {
}
for forbidden in [
- "impl Deref for RadrootsNostrGenericEventBuilder",
- "impl AsRef<nostr::EventBuilder> for RadrootsNostrGenericEventBuilder",
- "impl From<RadrootsNostrGenericEventBuilder> for nostr::EventBuilder",
- "impl Into<nostr::EventBuilder> for RadrootsNostrGenericEventBuilder",
- "impl Deref for RadrootsNostrExternalSigningRequest",
- "impl AsRef<nostr::UnsignedEvent> for RadrootsNostrExternalSigningRequest",
- "impl From<RadrootsNostrExternalSigningRequest> for nostr::UnsignedEvent",
- "impl Into<nostr::UnsignedEvent> for RadrootsNostrExternalSigningRequest",
- "impl Deserialize for RadrootsNostrExternalSigningRequest",
+ "impl Deref for GenericBuilder",
+ "impl AsRef<nostr::EventBuilder> for GenericBuilder",
+ "impl From<GenericBuilder> for nostr::EventBuilder",
+ "impl Into<nostr::EventBuilder> for GenericBuilder",
+ "impl Deref for ExternalSigningRequest",
+ "impl AsRef<nostr::UnsignedEvent> for ExternalSigningRequest",
+ "impl From<ExternalSigningRequest> for nostr::UnsignedEvent",
+ "impl Into<nostr::UnsignedEvent> for ExternalSigningRequest",
+ "impl Deserialize for ExternalSigningRequest",
"fn into_unsigned_event",
"fn as_unsigned_event",
"fn unsigned_event_mut",
diff --git a/crates/nostr/tests/nip09_deletion_request_profile.rs b/crates/nostr/tests/nip09_deletion_request_profile.rs
@@ -1,3 +1,4 @@
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_event::{
envelope::kind::KIND_DELETION_REQUEST,
post::deletion::{
@@ -5,14 +6,13 @@ use radroots_event::{
},
};
use radroots_event_codec::admission::deletion::verify_and_admit_nip09_deletion_request_event;
-use radroots_nostr::error::RadrootsNostrError;
+use radroots_nostr::Error;
use radroots_nostr::event::Kind as RadrootsNostrKind;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::event::radroots_event_from_nostr;
-use radroots_nostr::events::deletion::radroots_nostr_build_nip09_deletion_request_event;
-use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-use radroots_nostr::types::RadrootsNostrKeys;
-use radroots_nostr::types::RadrootsNostrSecretKey;
+use radroots_nostr::event::from_nostr;
+use radroots_nostr::event::{
+ GenericBuilder, build_nip09_deletion_request as build_nip09_deletion_request_event,
+};
use radroots_test_fixtures::{FIXTURE_ALICE_SECRET_KEY_HEX, FIXTURE_BOB_PUBLIC_KEY_HEX};
const CREATED_AT: u64 = 1_784_347_200;
@@ -33,7 +33,7 @@ fn typed_nip09_deletion_request_signs_exact_tags_and_admits() {
tag(&["k", "30402"]),
];
- let event = radroots_nostr_build_nip09_deletion_request_event(&request)
+ let event = build_nip09_deletion_request_event(&request)
.expect("typed NIP-09 builder")
.custom_created_at(created_at)
.sign_with_keys(&fixture_keys())
@@ -46,7 +46,7 @@ fn typed_nip09_deletion_request_signs_exact_tags_and_admits() {
event.verify().expect("valid deletion-request signature");
let admitted = verify_and_admit_nip09_deletion_request_event(
- radroots_event_from_nostr(&event).expect("deletion-request event adapter"),
+ from_nostr(&event).expect("deletion-request event adapter"),
)
.expect("deletion-request admission");
assert_eq!(
@@ -70,7 +70,7 @@ fn typed_nip09_deletion_request_signs_exact_tags_and_admits() {
#[test]
fn generic_kind_five_builder_cannot_bypass_typed_deletion_authoring() {
- let error = RadrootsNostrGenericEventBuilder::new(
+ let error = GenericBuilder::new(
RadrootsNostrKind::Custom(KIND_DELETION_REQUEST as u16),
"Raw deletion request",
)
@@ -79,7 +79,7 @@ fn generic_kind_five_builder_cannot_bypass_typed_deletion_authoring() {
assert!(matches!(
error,
- RadrootsNostrError::TypedAuthoringRequired { kind }
+ Error::TypedAuthoringRequired { kind }
if kind == KIND_DELETION_REQUEST as u16
));
}
diff --git a/crates/nostr/tests/nip10_reply_profile.rs b/crates/nostr/tests/nip10_reply_profile.rs
@@ -1,3 +1,4 @@
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_event::post::reply::{AuthoredNip10Reply, Nip10ReplyReference};
use radroots_event_codec::{
admission::{
@@ -6,15 +7,13 @@ use radroots_event_codec::{
},
decode::reply::RadrootsNip10ReplyStyle,
};
-use radroots_nostr::error::RadrootsNostrError;
+use radroots_nostr::Error;
+use radroots_nostr::event::GenericBuilder;
use radroots_nostr::event::Kind as RadrootsNostrKind;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::event::radroots_event_from_nostr;
-use radroots_nostr::events::reply::radroots_nostr_build_nip10_reply_event;
+use radroots_nostr::event::build_nip10_reply as build_nip10_reply_event;
+use radroots_nostr::event::from_nostr;
use radroots_nostr::tag::Tag as RadrootsNostrTag;
-use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-use radroots_nostr::types::RadrootsNostrKeys;
-use radroots_nostr::types::RadrootsNostrSecretKey;
use radroots_test_fixtures::{
FIXTURE_ALICE_SECRET_KEY_HEX, FIXTURE_BOB_PUBLIC_KEY_HEX, FIXTURE_CAROL_PUBLIC_KEY_HEX,
RELAY_PRIMARY_WSS, RELAY_SECONDARY_WSS,
@@ -36,7 +35,7 @@ fn typed_nip10_reply_builders_sign_exact_marked_direct_and_nested_profiles() {
let direct =
AuthoredNip10Reply::direct("Direct reply", root.clone()).expect("authored direct reply");
- let direct_event = radroots_nostr_build_nip10_reply_event(&direct)
+ let direct_event = build_nip10_reply_event(&direct)
.expect("typed direct Reply builder")
.custom_created_at(created_at)
.sign_with_keys(&keys)
@@ -60,7 +59,7 @@ fn typed_nip10_reply_builders_sign_exact_marked_direct_and_nested_profiles() {
);
let nested =
AuthoredNip10Reply::nested("Nested reply", root, parent).expect("authored nested reply");
- let nested_event = radroots_nostr_build_nip10_reply_event(&nested)
+ let nested_event = build_nip10_reply_event(&nested)
.expect("typed nested Reply builder")
.custom_created_at(created_at)
.sign_with_keys(&keys)
@@ -77,7 +76,7 @@ fn typed_nip10_reply_builders_sign_exact_marked_direct_and_nested_profiles() {
);
nested_event.verify().expect("valid nested Reply signature");
let admitted = verify_and_admit_nip10_reply_event(
- radroots_event_from_nostr(&nested_event).expect("nested Reply adapter"),
+ from_nostr(&nested_event).expect("nested Reply adapter"),
)
.expect("nested Reply admission");
assert!(!admitted.projection().is_direct());
@@ -103,12 +102,12 @@ fn signed_nip10_reply_is_thread_excluded_before_semantic_reply_admission() {
),
)
.expect("authored direct reply");
- let event = radroots_nostr_build_nip10_reply_event(&reply)
+ let event = build_nip10_reply_event(&reply)
.expect("typed Reply builder")
.custom_created_at(RadrootsNostrTimestamp::from_secs(CREATED_AT))
.sign_with_keys(&fixture_keys())
.expect("signed Reply");
- let envelope = radroots_event_from_nostr(&event).expect("Radroots event adapter");
+ let envelope = from_nostr(&event).expect("Radroots event adapter");
let candidate = match verify_and_admit_post_event(envelope).expect("post admission") {
RadrootsPostAdmissionOutcome::ThreadExcluded(candidate) => candidate,
@@ -143,7 +142,7 @@ fn verified_legacy_positional_nip10_reply_remains_tolerated_inbound() {
.custom_created_at(RadrootsNostrTimestamp::from_secs(CREATED_AT))
.sign_with_keys(&keys)
.expect("signed inbound fixture");
- let envelope = radroots_event_from_nostr(&event).expect("Radroots event adapter");
+ let envelope = from_nostr(&event).expect("Radroots event adapter");
let admitted =
verify_and_admit_nip10_reply_event(envelope).expect("legacy positional Reply admission");
@@ -161,19 +160,16 @@ fn verified_legacy_positional_nip10_reply_remains_tolerated_inbound() {
#[test]
fn generic_kind_one_builder_cannot_bypass_typed_nip10_reply_authoring() {
let keys = fixture_keys();
- let marked_reply = RadrootsNostrGenericEventBuilder::text_note("Raw marked reply").tags([
+ let marked_reply = GenericBuilder::text_note("Raw marked reply").tags([
RadrootsNostrTag::parse(["e", ROOT_EVENT_ID, RELAY_PRIMARY_WSS, "root"])
.expect("root reference"),
RadrootsNostrTag::parse(["p", FIXTURE_BOB_PUBLIC_KEY_HEX]).expect("root author reference"),
]);
- for builder in [
- RadrootsNostrGenericEventBuilder::text_note("Raw root"),
- marked_reply,
- ] {
+ for builder in [GenericBuilder::text_note("Raw root"), marked_reply] {
assert!(matches!(
builder.sign_with_keys(&keys),
- Err(RadrootsNostrError::TypedAuthoringRequired { kind })
+ Err(Error::TypedAuthoringRequired { kind })
if kind == RadrootsNostrKind::TextNote.as_u16()
));
}
diff --git a/crates/nostr/tests/nip17_conformance.rs b/crates/nostr/tests/nip17_conformance.rs
@@ -4,8 +4,7 @@ use nostr::{Keys, SecretKey};
use radroots_event::social::message::{Message, MessageRecipient};
use radroots_event::social::message_file::{MessageFile, MessageFileDimensions};
use radroots_nostr::nip17::{
- RadrootsNip17Rumor, RadrootsNip17WrapOptions, radroots_nostr_unwrap_gift_wrap,
- radroots_nostr_wrap_message, radroots_nostr_wrap_message_file,
+ Rumor, WrapOptions, unwrap_gift_wrap, wrap_message, wrap_message_file,
};
use radroots_test_fixtures::{
FIXTURE_ALICE_PUBLIC_KEY_HEX, FIXTURE_ALICE_SECRET_KEY_HEX, FIXTURE_BOB_PUBLIC_KEY_HEX,
@@ -96,12 +95,12 @@ async fn execute_message_roundtrip(vector: &Vector) {
reply_to: None,
subject: Some(input_str(vector, "subject").to_owned()),
};
- let events = radroots_nostr_wrap_message(&sender, &message, options(vector))
+ let events = wrap_message(&sender, &message, options(vector))
.await
.unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
assert_eq!(events.len(), expected_u64(vector, "event_count") as usize);
- let rumor = radroots_nostr_unwrap_gift_wrap(&receiver, &events[0])
+ let rumor = unwrap_gift_wrap(&receiver, &events[0])
.await
.unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
let rendered = format!("{rumor:?}");
@@ -113,7 +112,7 @@ async fn execute_message_roundtrip(vector: &Vector) {
assert!(!rendered.contains(private_value), "{}", vector.id);
}
match rumor {
- RadrootsNip17Rumor::Message(metadata) => {
+ Rumor::Message(metadata) => {
assert_eq!(
metadata.author,
expected_str(vector, "author"),
@@ -179,12 +178,12 @@ async fn execute_message_file_roundtrip(vector: &Vector) {
thumb: None,
fallbacks: Vec::new(),
};
- let events = radroots_nostr_wrap_message_file(&sender, &message, options(vector))
+ let events = wrap_message_file(&sender, &message, options(vector))
.await
.unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
assert_eq!(events.len(), expected_u64(vector, "event_count") as usize);
- let rumor = radroots_nostr_unwrap_gift_wrap(&receiver, &events[0])
+ let rumor = unwrap_gift_wrap(&receiver, &events[0])
.await
.unwrap_or_else(|error| panic!("{} failed: {error}", vector.id));
let rendered = format!("{rumor:?}");
@@ -199,7 +198,7 @@ async fn execute_message_file_roundtrip(vector: &Vector) {
assert!(!rendered.contains(private_value), "{}", vector.id);
}
match rumor {
- RadrootsNip17Rumor::MessageFile(metadata) => {
+ Rumor::MessageFile(metadata) => {
assert_eq!(
metadata.author,
expected_str(vector, "author"),
@@ -262,7 +261,7 @@ async fn execute_invalid_recipient(vector: &Vector) {
reply_to: None,
subject: None,
};
- let error = radroots_nostr_wrap_message(&sender, &message, options(vector))
+ let error = wrap_message(&sender, &message, options(vector))
.await
.expect_err("invalid recipient vector must fail");
assert_eq!(error.code(), expected_str(vector, "error"), "{}", vector.id);
@@ -271,12 +270,10 @@ async fn execute_invalid_recipient(vector: &Vector) {
assert!(!rendered.contains(&message.content), "{}", vector.id);
}
-fn options(vector: &Vector) -> RadrootsNip17WrapOptions {
- RadrootsNip17WrapOptions {
- include_sender: false,
- rumor_created_at: Some(input_u64(vector, "created_at")),
- gift_wrap_tags: Vec::new(),
- }
+fn options(vector: &Vector) -> WrapOptions {
+ WrapOptions::default()
+ .include_sender(false)
+ .with_rumor_created_at(input_u64(vector, "created_at"))
}
fn sender_keys() -> Keys {
diff --git a/crates/nostr/tests/nip22_comment_profile.rs b/crates/nostr/tests/nip22_comment_profile.rs
@@ -1,3 +1,4 @@
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_event::{
envelope::kind::{
KIND_CALENDAR_DATE_EVENT, KIND_CALENDAR_TIME_EVENT, KIND_CLASSIFIED_LISTING, KIND_COMMENT,
@@ -11,14 +12,11 @@ use radroots_event_codec::{
admission::comment::verify_and_admit_nip22_comment_event,
decode::comment::RadrootsInboundNip22CommentPosition,
};
-use radroots_nostr::error::RadrootsNostrError;
+use radroots_nostr::Error;
use radroots_nostr::event::Kind as RadrootsNostrKind;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::event::radroots_event_from_nostr;
-use radroots_nostr::events::comment::radroots_nostr_build_nip22_comment_event;
-use radroots_nostr::types::RadrootsNostrGenericEventBuilder;
-use radroots_nostr::types::RadrootsNostrKeys;
-use radroots_nostr::types::RadrootsNostrSecretKey;
+use radroots_nostr::event::from_nostr;
+use radroots_nostr::event::{GenericBuilder, build_nip22_comment as build_nip22_comment_event};
use radroots_test_fixtures::{
FIXTURE_ALICE_SECRET_KEY_HEX, FIXTURE_BOB_PUBLIC_KEY_HEX, FIXTURE_CAROL_PUBLIC_KEY_HEX,
RELAY_PRIMARY_WSS, RELAY_SECONDARY_WSS,
@@ -136,7 +134,7 @@ fn typed_nip22_comment_builders_sign_and_admit_all_exact_shapes() {
(nested_event, nested_event_tags, "nested"),
(nested_address, nested_address_tags, "nested"),
] {
- let event = radroots_nostr_build_nip22_comment_event(&comment)
+ let event = build_nip22_comment_event(&comment)
.expect("typed Comment builder")
.custom_created_at(created_at)
.sign_with_keys(&keys)
@@ -147,7 +145,7 @@ fn typed_nip22_comment_builders_sign_and_admit_all_exact_shapes() {
event.verify().expect("valid Comment signature");
let admitted = verify_and_admit_nip22_comment_event(
- radroots_event_from_nostr(&event).expect("Comment event adapter"),
+ from_nostr(&event).expect("Comment event adapter"),
)
.expect("Comment admission");
assert_eq!(
@@ -160,13 +158,13 @@ fn typed_nip22_comment_builders_sign_and_admit_all_exact_shapes() {
#[test]
fn generic_kind_1111_builder_cannot_bypass_typed_comment_authoring() {
let kind = RadrootsNostrKind::Custom(KIND_COMMENT as u16);
- let error = RadrootsNostrGenericEventBuilder::new(kind, "Raw Comment")
+ let error = GenericBuilder::new(kind, "Raw Comment")
.sign_with_keys(&fixture_keys())
.expect_err("generic kind 1111 must be reserved");
assert!(matches!(
error,
- RadrootsNostrError::TypedAuthoringRequired { kind: actual }
+ Error::TypedAuthoringRequired { kind: actual }
if actual == KIND_COMMENT as u16
));
}
diff --git a/crates/nostr/tests/package_boundary.rs b/crates/nostr/tests/package_boundary.rs
@@ -22,6 +22,8 @@ const README: &str = include_str!("../README.md");
const SIGNING_MODULE: &str = include_str!("../src/signing.rs");
const TAG_MODULE: &str = include_str!("../src/tag.rs");
const TYPES_MODULE: &str = include_str!("../src/types.rs");
+const COMPATIBILITY: &str = include_str!("../COMPATIBILITY.md");
+const PUBLIC_API: &str = include_str!("../../../docs/api/radroots_nostr.txt");
const IDENTITY_MANIFEST: &str = include_str!("../../identity/Cargo.toml");
const IDENTITY_KEY_MODULE: &str = include_str!("../../identity/src/key.rs");
const TRANSPORT_MANIFEST: &str = include_str!("../../transport_nostr/Cargo.toml");
@@ -102,12 +104,11 @@ fn manifest_has_final_identity_features_and_radroots_dependencies() {
}
let features = table_keys(MANIFEST, "[features]");
- for required in ["default", "std", "events", "signing", "nip17", "blossom"] {
- assert!(
- features.contains(required),
- "manifest is missing supported feature `{required}`"
- );
- }
+ assert_eq!(
+ features,
+ BTreeSet::from(["blossom", "default", "events", "nip17", "signing", "std"]),
+ "manifest feature vocabulary must match the Release V1 charter"
+ );
for feature in features {
let declaration = table_value(MANIFEST, "[features]", feature)
.unwrap_or_else(|| panic!("missing feature declaration `{feature}`"));
@@ -145,13 +146,29 @@ fn crate_root_establishes_the_final_public_module_skeleton() {
.collect::<Vec<_>>();
assert_eq!(
root_reexports,
- ["pub use error::RadrootsNostrError as Error;"],
+ ["pub use error::Error;"],
"the crate root must re-export only the canonical Error alias"
);
assert!(
!ROOT.contains("pub mod prelude"),
"lower-level Nostr crate must not publish a broad prelude"
);
+ for retired in [
+ "codec_adapters",
+ "draft_signing",
+ "error",
+ "event_adapters",
+ "event_verify",
+ "events",
+ "job_adapter",
+ "types",
+ "util",
+ ] {
+ assert!(
+ !ROOT.contains(&format!("pub mod {retired};")),
+ "superseded module remains public: `{retired}`"
+ );
+ }
}
#[test]
@@ -375,7 +392,7 @@ fn local_signer_consumes_only_the_opaque_secret_boundary() {
fn focused_nip_and_blossom_features_own_no_network_operations() {
for required in [
"blossom = [\"std\", \"dep:base64\", \"dep:radroots_blossom\"]",
- "nip17 = [\"std\", \"codec\", \"nostr/nip44\", \"nostr/nip59\"]",
+ "nip17 = [\"events\", \"nostr/nip44\", \"nostr/nip59\"]",
] {
assert!(
MANIFEST.contains(required),
@@ -383,9 +400,9 @@ fn focused_nip_and_blossom_features_own_no_network_operations() {
);
}
for required in [
- "pub async fn radroots_nostr_wrap_message<T>(",
- "pub async fn radroots_nostr_wrap_message_file<T>(",
- "pub async fn radroots_nostr_unwrap_gift_wrap<T>(",
+ "pub async fn wrap_message<T>(",
+ "pub async fn wrap_message_file<T>(",
+ "pub async fn unwrap_gift_wrap<T>(",
"pub const fn code(&self) -> &'static str",
] {
assert!(
@@ -394,9 +411,9 @@ fn focused_nip_and_blossom_features_own_no_network_operations() {
);
}
for required in [
- "pub fn radroots_nostr_sign_blossom_authorization(",
- "pub fn radroots_nostr_encode_blossom_authorization_header(",
- "pub fn radroots_nostr_decode_verify_blossom_authorization_header(",
+ "pub fn sign_authorization(",
+ "pub fn encode_authorization_header(",
+ "pub fn decode_verify_authorization_header(",
] {
assert!(
BLOSSOM_MODULE.contains(required),
@@ -495,9 +512,16 @@ fn workspace_consumers_do_not_use_superseded_nostr_alias_paths() {
let source = fs::read_to_string(&source_path)
.unwrap_or_else(|error| panic!("failed to read {}: {error}", source_path.display()));
for forbidden in [
+ "radroots_nostr::codec_adapters::",
+ "radroots_nostr::draft_signing::",
"radroots_nostr::error::",
+ "radroots_nostr::event_adapters::",
+ "radroots_nostr::event_verify::",
+ "radroots_nostr::events::",
+ "radroots_nostr::job_adapter::",
"radroots_nostr::prelude",
"radroots_nostr::types::",
+ "radroots_nostr::util::",
] {
assert!(
!source.contains(forbidden),
@@ -508,6 +532,62 @@ fn workspace_consumers_do_not_use_superseded_nostr_alias_paths() {
}
}
+#[test]
+fn superseded_surface_retirement_is_explicit_and_release_bounded() {
+ assert!(!MANIFEST.contains("codec = []"));
+ for forbidden in ["pub fn radroots_nostr_", "pub async fn radroots_nostr_"] {
+ for source_path in rust_sources(&PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src")) {
+ let source = fs::read_to_string(&source_path).unwrap_or_else(|error| {
+ panic!("failed to read {}: {error}", source_path.display())
+ });
+ assert!(
+ !source.contains(forbidden),
+ "{} retains prefixed public item `{forbidden}`",
+ source_path.display()
+ );
+ }
+ }
+ for required in [
+ "publish = false",
+ "outside the authorized `oss/lib` and `oss/sdk` crate-surface edit boundary",
+ "no compatibility path was restored",
+ "Step 313 is the exact final pre-release audit",
+ ] {
+ let authority = if required == "publish = false" {
+ MANIFEST
+ } else {
+ COMPATIBILITY
+ };
+ assert!(
+ authority.contains(required),
+ "retirement contract is missing `{required}`"
+ );
+ }
+
+ let public_modules = PUBLIC_API
+ .lines()
+ .filter_map(|line| line.strip_prefix("pub mod radroots_nostr::"))
+ .collect::<BTreeSet<_>>();
+ assert_eq!(
+ public_modules,
+ BTreeSet::from([
+ "blossom", "event", "filter", "key", "nip17", "signing", "tag"
+ ]),
+ "reviewed API baseline must expose only chartered modules"
+ );
+ for forbidden in [
+ "::RadrootsNostr",
+ "::radroots_nostr_",
+ "pub radroots_nostr::event::ApplicationHandlerSpec::",
+ "pub radroots_nostr::nip17::WrapOptions::",
+ ] {
+ assert!(
+ !PUBLIC_API.contains(forbidden),
+ "reviewed API baseline retains forbidden surface `{forbidden}`"
+ );
+ }
+}
+
fn rust_sources(root: &Path) -> Vec<PathBuf> {
let mut pending = vec![root.to_path_buf()];
let mut sources = Vec::new();
diff --git a/crates/nostr/tests/post_profile.rs b/crates/nostr/tests/post_profile.rs
@@ -1,6 +1,7 @@
#[path = "../src/test_fixtures.rs"]
mod test_fixtures;
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_blossom::{BlobDescriptor, BlobUrl, MediaType, Sha256};
use radroots_event::{
media::AuthoredImage,
@@ -8,13 +9,9 @@ use radroots_event::{
AuthoredAsk, AuthoredPhotoUpdate, AuthoredPostImage, AuthoredUpdate, PostImageDimensions,
},
};
-use radroots_nostr::{
- event::Timestamp as RadrootsNostrTimestamp,
- events::post::{
- radroots_nostr_build_ask_event, radroots_nostr_build_photo_update_event,
- radroots_nostr_build_update_event,
- },
- types::{RadrootsNostrKeys, RadrootsNostrSecretKey},
+use radroots_nostr::event::{
+ Timestamp as RadrootsNostrTimestamp, build_ask as build_ask_event,
+ build_photo_update as build_photo_update_event, build_update as build_update_event,
};
#[test]
@@ -24,7 +21,7 @@ fn typed_post_builders_preserve_strict_wire_profiles() {
);
let created_at = RadrootsNostrTimestamp::from_secs(1_784_347_200);
let update = AuthoredUpdate::new("Farm update").unwrap();
- let event = radroots_nostr_build_update_event(&update)
+ let event = build_update_event(&update)
.unwrap()
.custom_created_at(created_at)
.sign_with_keys(&keys)
@@ -37,7 +34,7 @@ fn typed_post_builders_preserve_strict_wire_profiles() {
let image = authored_image();
let photo =
AuthoredPhotoUpdate::new(format!("Harvest {}", image.url()), vec![image.clone()]).unwrap();
- let event = radroots_nostr_build_photo_update_event(&photo)
+ let event = build_photo_update_event(&photo)
.unwrap()
.custom_created_at(created_at)
.sign_with_keys(&keys)
@@ -47,7 +44,7 @@ fn typed_post_builders_preserve_strict_wire_profiles() {
assert!(event.verify().is_ok());
let ask = AuthoredAsk::new(format!("Is this ready? {}", image.url()), vec![image]).unwrap();
- let event = radroots_nostr_build_ask_event(&ask)
+ let event = build_ask_event(&ask)
.unwrap()
.custom_created_at(created_at)
.sign_with_keys(&keys)
diff --git a/crates/nostr/tests/profile_event_builder.rs b/crates/nostr/tests/profile_event_builder.rs
@@ -1,11 +1,10 @@
#[path = "../src/test_fixtures.rs"]
mod test_fixtures;
+use nostr::{Keys as RadrootsNostrKeys, SecretKey as RadrootsNostrSecretKey};
use radroots_event::profile::AuthoredProfile;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::events::metadata::radroots_nostr_build_profile_event;
-use radroots_nostr::types::RadrootsNostrKeys;
-use radroots_nostr::types::RadrootsNostrSecretKey;
+use radroots_nostr::event::build_profile as build_profile_event;
#[test]
fn typed_profile_builder_preserves_the_strict_replacement_snapshot() {
@@ -19,7 +18,7 @@ fn typed_profile_builder_preserves_the_strict_replacement_snapshot() {
.with_about("Tree fruit")
.with_bot(false);
- let event = radroots_nostr_build_profile_event(&profile)
+ let event = build_profile_event(&profile)
.unwrap()
.custom_created_at(created_at)
.sign_with_keys(&keys)
diff --git a/crates/nostr_runtime/src/types.rs b/crates/nostr_runtime/src/types.rs
@@ -1,10 +1,10 @@
use alloc::string::String;
use nostr::PublicKey as RadrootsNostrPublicKey;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
-use radroots_nostr::events::post::radroots_nostr_post_events_filter;
+use radroots_nostr::event::post_filter;
#[cfg(feature = "nostr-client")]
use radroots_nostr::filter::Filter as RadrootsNostrFilter;
-use radroots_nostr::filter::radroots_nostr_kind;
+use radroots_nostr::filter::kind as nostr_kind;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RadrootsNostrSubscriptionPolicy {
@@ -59,7 +59,7 @@ impl RadrootsNostrSubscriptionSpec {
since_unix: Option<u64>,
policy: RadrootsNostrSubscriptionPolicy,
) -> Self {
- Self::streaming(radroots_nostr_post_events_filter(limit, since_unix)).with_policy(policy)
+ Self::streaming(post_filter(limit, since_unix)).with_policy(policy)
}
#[cfg(feature = "nostr-client")]
@@ -69,7 +69,7 @@ impl RadrootsNostrSubscriptionSpec {
since_unix: Option<u64>,
policy: RadrootsNostrSubscriptionPolicy,
) -> Self {
- let mut filter = RadrootsNostrFilter::new().kind(radroots_nostr_kind(kind));
+ let mut filter = RadrootsNostrFilter::new().kind(nostr_kind(kind));
if let Some(limit) = limit {
filter = filter.limit(limit.into());
}
diff --git a/crates/nostr_signer/src/nip46.rs b/crates/nostr_signer/src/nip46.rs
@@ -5,8 +5,8 @@ use nostr::{
};
use radroots_identity::PublicIdentity;
use radroots_nostr::event::Event as RadrootsNostrEvent;
+use radroots_nostr::event::GenericBuilder;
use radroots_nostr::event::Kind as RadrootsNostrKind;
-use radroots_nostr::event::RadrootsNostrGenericEventBuilder;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
use radroots_nostr::filter::Filter as RadrootsNostrFilter;
use radroots_nostr::tag::Tag as RadrootsNostrTag;
@@ -182,12 +182,12 @@ impl<S: RadrootsNostrSignerNip46Signer> RadrootsNostrSignerNip46Codec<S> {
client_public_key: RadrootsNostrPublicKey,
request_id: impl Into<String>,
response: RadrootsNostrConnectResponse,
- ) -> Result<RadrootsNostrGenericEventBuilder, RadrootsNostrSignerError> {
+ ) -> Result<GenericBuilder, RadrootsNostrSignerError> {
let envelope = response.into_envelope(request_id.into())?;
let payload = serde_json::to_string(&envelope).map_err(RadrootsNostrConnectError::from)?;
let ciphertext = self.signer.encrypt_response(&client_public_key, &payload)?;
- Ok(RadrootsNostrGenericEventBuilder::new(
+ Ok(GenericBuilder::new(
RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
ciphertext,
)
@@ -317,7 +317,7 @@ where
client_public_key: RadrootsNostrPublicKey,
request_id: impl Into<String>,
response: RadrootsNostrConnectResponse,
- ) -> Result<RadrootsNostrGenericEventBuilder, RadrootsNostrSignerError> {
+ ) -> Result<GenericBuilder, RadrootsNostrSignerError> {
self.codec
.build_response_event(client_public_key, request_id, response)
}
@@ -860,8 +860,8 @@ mod tests {
use nostr::{Keys, SecretKey, Timestamp, UnsignedEvent};
use radroots_identity::{PublicIdentity, PublicKey as IdentityPublicKey};
use radroots_nostr::event::Event as RadrootsNostrEvent;
+ use radroots_nostr::event::GenericBuilder;
use radroots_nostr::event::Kind as RadrootsNostrKind;
- use radroots_nostr::event::RadrootsNostrGenericEventBuilder;
use radroots_nostr::tag::TagKind as RadrootsNostrTagKind;
use radroots_nostr_connect::prelude::{
RADROOTS_NOSTR_CONNECT_RPC_KIND, RadrootsNostrConnectMethod,
@@ -1222,7 +1222,7 @@ mod tests {
let client_public_key = fixture_carol_public_key();
let request = request_message("req-parse", RadrootsNostrConnectRequest::Ping);
let raw = serde_json::to_string(&request).expect("serialize request");
- let event = RadrootsNostrGenericEventBuilder::new(
+ let event = GenericBuilder::new(
RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
raw,
)
diff --git a/crates/outbox/Cargo.toml b/crates/outbox/Cargo.toml
@@ -42,6 +42,7 @@ radroots_identity = { workspace = true, default-features = false, features = [
radroots_nostr = { workspace = true, default-features = false, features = [
"std",
"events",
+ "signing",
] }
tempfile = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt"] }
diff --git a/crates/outbox/src/store.rs b/crates/outbox/src/store.rs
@@ -3406,7 +3406,7 @@ mod tests {
canonical_trade_mutation_content,
};
use radroots_identity::PublicKey;
- use radroots_nostr::draft_signing::radroots_nostr_sign_frozen_draft;
+ use radroots_nostr::signing::sign_frozen_draft;
const FIXTURE_ALICE_SECRET_KEY_HEX: &str =
"10c5304d6c9ae3a1a16f7860f1cc8f5e3a76225a2663b3a989a0d775919b7df5";
@@ -3589,8 +3589,7 @@ mod tests {
fn signed_trade_mutation(canonical: &TradeCanonicalMutationV1) -> (EventDraft, SignedEvent) {
let draft = trade_mutation_draft(canonical);
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed trade event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed trade event");
(draft, signed_event)
}
@@ -4286,8 +4285,8 @@ mod tests {
.expect("pool outbox");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "preflight");
- let signed_event = radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft)
- .expect("signed preflight event");
+ let signed_event =
+ sign_frozen_draft(&fixture_keys(), &draft).expect("signed preflight event");
let input = signed_operation_input(draft.clone(), signed_event.clone(), 1_000)
.with_idempotency_key("preflight-idem");
outbox
@@ -4312,8 +4311,8 @@ mod tests {
.expect("matching existing preflight");
let changed_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "preflight changed");
- let changed_signed = radroots_nostr_sign_frozen_draft(&fixture_keys(), &changed_draft)
- .expect("changed signed event");
+ let changed_signed =
+ sign_frozen_draft(&fixture_keys(), &changed_draft).expect("changed signed event");
let conflict = signed_operation_input(changed_draft, changed_signed, 1_100)
.with_idempotency_key("preflight-idem");
assert!(matches!(
@@ -4324,9 +4323,8 @@ mod tests {
));
let transaction_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "transaction");
- let transaction_signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &transaction_draft)
- .expect("transaction signed event");
+ let transaction_signed = sign_frozen_draft(&fixture_keys(), &transaction_draft)
+ .expect("transaction signed event");
let transaction_input =
signed_operation_input(transaction_draft.clone(), transaction_signed, 2_000)
.with_idempotency_key("transaction-idem");
@@ -4343,9 +4341,8 @@ mod tests {
let transaction_changed =
generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "transaction changed");
- let transaction_changed_signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &transaction_changed)
- .expect("transaction changed signed event");
+ let transaction_changed_signed = sign_frozen_draft(&fixture_keys(), &transaction_changed)
+ .expect("transaction changed signed event");
let transaction_conflict =
signed_operation_input(transaction_changed, transaction_changed_signed, 2_100)
.with_idempotency_key("transaction-idem");
@@ -4465,8 +4462,8 @@ mod tests {
async fn defensive_storage_decoding_and_remaining_idempotency_edges_are_explicit() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "defensive storage");
- let signed_event = radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft)
- .expect("signed defensive event");
+ let signed_event =
+ sign_frozen_draft(&fixture_keys(), &draft).expect("signed defensive event");
let signed_receipt = outbox
.enqueue_signed_operation(signed_operation_input(
draft.clone(),
@@ -4477,8 +4474,8 @@ mod tests {
.expect("signed insert without idempotency key");
let keyed_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "keyed public insert");
- let keyed_signed = radroots_nostr_sign_frozen_draft(&fixture_keys(), &keyed_draft)
- .expect("keyed signed event");
+ let keyed_signed =
+ sign_frozen_draft(&fixture_keys(), &keyed_draft).expect("keyed signed event");
outbox
.enqueue_signed_operation(
signed_operation_input(keyed_draft, keyed_signed, 1_100)
@@ -4487,8 +4484,8 @@ mod tests {
.await
.expect("keyed public signed insert");
let changed_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "keyed public conflict");
- let changed_signed = radroots_nostr_sign_frozen_draft(&fixture_keys(), &changed_draft)
- .expect("changed signed event");
+ let changed_signed =
+ sign_frozen_draft(&fixture_keys(), &changed_draft).expect("changed signed event");
assert!(matches!(
outbox
.enqueue_signed_operation(
@@ -4504,9 +4501,8 @@ mod tests {
FIXTURE_ALICE_PUBLIC_KEY_HEX,
"not a semantic trade mutation",
);
- let invalid_trade_signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &invalid_trade_draft)
- .expect("invalid trade draft still forms a valid signed event");
+ let invalid_trade_signed = sign_frozen_draft(&fixture_keys(), &invalid_trade_draft)
+ .expect("invalid trade draft still forms a valid signed event");
assert!(matches!(
outbox
.preflight_signed_trade_mutation_idempotency(&signed_trade_mutation_input(
@@ -4567,9 +4563,8 @@ mod tests {
.expect("trade insert without idempotency key");
let transaction_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "transaction no key");
- let transaction_signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &transaction_draft)
- .expect("transaction signed event");
+ let transaction_signed = sign_frozen_draft(&fixture_keys(), &transaction_draft)
+ .expect("transaction signed event");
let mut transaction = outbox.pool().begin().await.expect("begin transaction");
outbox
.enqueue_signed_operation_in_transaction(
@@ -4911,8 +4906,7 @@ mod tests {
));
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "plan lifecycle");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("sign plan lifecycle");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("sign plan lifecycle");
let first = outbox
.enqueue_signed_operation(
RadrootsOutboxSignedOperationInput::new(
@@ -5085,8 +5079,7 @@ mod tests {
.enqueue_operation(operation_input(draft.clone(), 1_000))
.await
.expect("enqueue unsigned");
- let signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("sign queued event");
+ let signed = sign_frozen_draft(&fixture_keys(), &draft).expect("sign queued event");
let claimed = outbox
.claim_next_ready_event("signer", "sign-claim", 2_000, 1_000)
.await
@@ -5106,8 +5099,8 @@ mod tests {
));
let other_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "different event");
- let other_signed = radroots_nostr_sign_frozen_draft(&fixture_keys(), &other_draft)
- .expect("sign different event");
+ let other_signed =
+ sign_frozen_draft(&fixture_keys(), &other_draft).expect("sign different event");
assert!(matches!(
outbox
.complete_signing(receipt.outbox_event_id, "sign-claim", other_signed, 1_020,)
@@ -5266,8 +5259,8 @@ mod tests {
let signed_outbox = RadrootsOutbox::open_memory().await.expect("open signed");
let signed_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "signed race");
- let signed_event = radroots_nostr_sign_frozen_draft(&fixture_keys(), &signed_draft)
- .expect("sign race event");
+ let signed_event =
+ sign_frozen_draft(&fixture_keys(), &signed_draft).expect("sign race event");
signed_outbox
.enqueue_signed_operation(signed_operation_input(signed_draft, signed_event, 1_000))
.await
@@ -5291,8 +5284,7 @@ mod tests {
async fn claimed_publish_mutations_enforce_plan_identity_and_atomic_updates() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "publish guards");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("sign publish guards");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("sign publish guards");
let receipt = outbox
.enqueue_signed_operation(signed_operation_input(draft, signed_event, 1_000))
.await
@@ -5532,8 +5524,7 @@ mod tests {
FIXTURE_ALICE_PUBLIC_KEY_HEX,
)
.expect("ephemeral draft");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed");
let unsigned_error = outbox
.enqueue_operation(operation_input(draft.clone(), 1_000))
@@ -5873,8 +5864,7 @@ mod tests {
async fn no_wait_delivery_plan_persists_directly_and_completes_without_target_satisfaction() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "no wait");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -6168,8 +6158,7 @@ mod tests {
async fn signed_enqueue_claims_ready_delivery_targets_and_records_attempts() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "signed");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(signed_operation_input(draft, signed_event.clone(), 1_000))
.await
@@ -6271,8 +6260,7 @@ mod tests {
async fn required_target_plan_evaluation_uses_persisted_fingerprints() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "required target");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let optional = nostr_target(NOSTR_PRIMARY_WSS);
let required = nostr_target(NOSTR_SECONDARY_WSS);
let receipt = outbox
@@ -6382,8 +6370,7 @@ mod tests {
FIXTURE_ALICE_PUBLIC_KEY_HEX,
"required target optional failure",
);
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let optional = nostr_target(NOSTR_PRIMARY_WSS);
let required = nostr_target(NOSTR_SECONDARY_WSS);
let receipt = outbox
@@ -6515,8 +6502,7 @@ mod tests {
] {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, terminal_status.as_str());
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -6621,8 +6607,7 @@ mod tests {
async fn publish_claims_one_delivery_plan_and_rejects_sibling_target_outcomes() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "duplicate endpoint plans");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let first = outbox
.enqueue_signed_operation(
RadrootsOutboxSignedOperationInput::new(
@@ -6764,8 +6749,7 @@ mod tests {
async fn active_plan_terminal_failure_leaves_sibling_claimable() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "plan scoped terminal");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let first = outbox
.enqueue_signed_operation(
RadrootsOutboxSignedOperationInput::new(
@@ -6907,8 +6891,7 @@ mod tests {
async fn cancel_claimed_event_marks_every_delivery_plan_cancelled() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "cancel all plans");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let first = outbox
.enqueue_signed_operation(
RadrootsOutboxSignedOperationInput::new(
@@ -6991,8 +6974,7 @@ mod tests {
async fn quorum_accepted_delivery_plan_round_trips_and_completes_after_required_target() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "at least");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7059,8 +7041,7 @@ mod tests {
async fn publish_attempt_stays_retryable_while_delivery_targets_remain_ready() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "retryable");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(signed_operation_input(draft, signed_event, 1_000))
.await
@@ -7101,8 +7082,7 @@ mod tests {
async fn reticulum_reject_targets_are_deferred_until_implemented_and_not_ready() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum rejected");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7171,8 +7151,7 @@ mod tests {
async fn reticulum_deferred_targets_do_not_retry_or_satisfy_delivery() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum deferred");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7239,8 +7218,7 @@ mod tests {
let default_behavior_draft =
generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum deferred");
let default_behavior_signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &default_behavior_draft)
- .expect("signed event");
+ sign_frozen_draft(&fixture_keys(), &default_behavior_draft).expect("signed event");
let default_behavior_preflight = outbox
.preflight_signed_operation_idempotency(&RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7268,8 +7246,7 @@ mod tests {
async fn repeated_reticulum_signed_delivery_reuses_one_logical_operation_and_plan() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum repeated");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let first = outbox
.enqueue_signed_operation(
RadrootsOutboxSignedOperationInput::new(
@@ -7337,8 +7314,8 @@ mod tests {
async fn reticulum_events_report_deferred_records() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let reject_draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum record");
- let reject_signed_event = radroots_nostr_sign_frozen_draft(&fixture_keys(), &reject_draft)
- .expect("reticulum signed event");
+ let reject_signed_event =
+ sign_frozen_draft(&fixture_keys(), &reject_draft).expect("reticulum signed event");
let reject = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7359,8 +7336,7 @@ mod tests {
let deferred_draft =
generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "reticulum deferred record");
let deferred_signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &deferred_draft)
- .expect("deferred signed event");
+ sign_frozen_draft(&fixture_keys(), &deferred_draft).expect("deferred signed event");
let deferred = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7491,8 +7467,7 @@ mod tests {
.expect("claim")
.expect("claimed");
assert_eq!(claimed.active_delivery_plan_id, None);
- let signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
+ let signed = sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
outbox
.complete_signing(receipt.outbox_event_id, "claim-a", signed, 1_100)
@@ -7528,8 +7503,7 @@ mod tests {
async fn explicit_all_targets_completes_after_nostr_success_with_reticulum_preserved() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "explicit all targets");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7630,8 +7604,7 @@ mod tests {
async fn explicit_quorum_rejects_deferred_targets_as_required_success_capacity() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "explicit quorum");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let err = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7667,8 +7640,7 @@ mod tests {
async fn explicit_nostr_and_reticulum_preserves_ready_nostr_work() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "explicit reticulum");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7724,8 +7696,7 @@ mod tests {
async fn accepted_delivery_target_can_advance_to_strict_success_status() {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "accepted then delivered");
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7832,8 +7803,7 @@ mod tests {
] {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, content);
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -7976,8 +7946,7 @@ mod tests {
] {
let outbox = RadrootsOutbox::open_memory().await.expect("open");
let draft = generic_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, content);
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &draft).expect("signed event");
let receipt = outbox
.enqueue_signed_operation(RadrootsOutboxSignedOperationInput::new(
"publish_post",
@@ -8110,8 +8079,7 @@ mod tests {
.await
.expect("claim")
.expect("claimed");
- let signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
+ let signed = sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
outbox
.complete_signing(
receipt.outbox_event_id,
@@ -8181,8 +8149,7 @@ mod tests {
.await
.expect("claim")
.expect("claimed");
- let signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
+ let signed = sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
outbox
.complete_signing(
receipt.outbox_event_id,
@@ -8242,8 +8209,7 @@ mod tests {
.await
.expect("claim")
.expect("claimed");
- let signed =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
+ let signed = sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed");
let mut wire = signed.wire().clone();
wire.sig = "0".repeat(128);
let raw_json = serde_json::to_string(&wire).expect("invalid-signature wire JSON");
diff --git a/crates/replica_sync/src/ingest.rs b/crates/replica_sync/src/ingest.rs
@@ -1636,7 +1636,7 @@ mod tests {
use radroots_event_codec::encode::farm as farm_list_sets;
use radroots_event_codec::encode::list_set as list_set_encode;
use radroots_event_codec::encode::plot as plot_encode;
- use radroots_nostr::event::radroots_event_from_nostr;
+ use radroots_nostr::event::from_nostr;
use radroots_replica_schema::farm::IFarmFields;
use radroots_replica_schema::farm_gcs_location::IFarmGcsLocationFields;
use radroots_replica_schema::farm_member::IFarmMemberFields;
@@ -2072,7 +2072,7 @@ mod tests {
.custom_created_at(Timestamp::from_secs(created_at))
.sign_with_keys(&keys)
.expect("signed listing event");
- radroots_event_from_nostr(&event).expect("listing event adapter")
+ from_nostr(&event).expect("listing event adapter")
}
fn focused_listing_event(author: &str, created_at: u64, d_tag: &str) -> EventEnvelope {
diff --git a/crates/transport_nostr/src/publish.rs b/crates/transport_nostr/src/publish.rs
@@ -1050,7 +1050,7 @@ mod tests {
use radroots_event::draft::{EventDraft, SignedEvent};
use radroots_event::envelope::kind::KIND_GEOCHAT;
use radroots_event::wire::Nip01EventWire;
- use radroots_nostr::draft_signing::radroots_nostr_sign_frozen_draft;
+ use radroots_nostr::signing::sign_frozen_draft;
const FIXTURE_ALICE_SECRET_KEY_HEX: &str =
"10c5304d6c9ae3a1a16f7860f1cc8f5e3a76225a2663b3a989a0d775919b7df5";
@@ -1070,7 +1070,7 @@ mod tests {
FIXTURE_ALICE_PUBLIC_KEY_HEX,
)
.expect("draft");
- let signed_event = radroots_nostr_sign_frozen_draft(&keys, &draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&keys, &draft).expect("signed event");
let raw_event = RadrootsNostrEvent::from_json(signed_event.raw_json()).expect("raw event");
(raw_event, signed_event)
}
diff --git a/crates/transport_nostr/tests/transport.rs b/crates/transport_nostr/tests/transport.rs
@@ -9,11 +9,11 @@ use radroots_event::wire::v1::DEFAULT_RAW_JSON_MAX_BYTES;
use radroots_event_store::{
RadrootsEventStore, RadrootsTransportObservationRow, RadrootsTransportObservationType,
};
-use radroots_nostr::draft_signing::radroots_nostr_sign_frozen_draft;
use radroots_nostr::event::Kind as RadrootsNostrKind;
use radroots_nostr::event::Timestamp as RadrootsNostrTimestamp;
use radroots_nostr::filter::Filter as RadrootsNostrFilter;
-use radroots_nostr::filter::radroots_nostr_filter_tag;
+use radroots_nostr::filter::with_tag;
+use radroots_nostr::signing::sign_frozen_draft;
use radroots_nostr::tag::Tag as RadrootsNostrTag;
use radroots_nostr::tag::TagKind as RadrootsNostrTagKind;
use radroots_outbox::{
@@ -475,8 +475,7 @@ async fn complete_claimed_signing(
if let Some(signed_event) = claimed.signed_event.clone() {
return signed_event;
}
- let signed_event =
- radroots_nostr_sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed event");
+ let signed_event = sign_frozen_draft(&fixture_keys(), &claimed.draft).expect("signed event");
outbox
.complete_signing(
claimed.outbox_event_id,
@@ -598,7 +597,7 @@ fn invalid_contract_shape_raw_event() -> String {
}
fn post_relay_fetch_filter(limit: usize) -> RadrootsNostrFilter {
- radroots_nostr_filter_tag(
+ with_tag(
RadrootsNostrFilter::new()
.kind(RadrootsNostrKind::Custom(
u16::try_from(KIND_POST).expect("post kind must fit NIP-01"),
@@ -2614,7 +2613,7 @@ async fn fetch_rejects_out_of_filter_events_before_store_mutation() {
relay_url: RELAY_PRIMARY_WSS.to_owned(),
},
]);
- let filter = radroots_nostr_filter_tag(
+ let filter = with_tag(
RadrootsNostrFilter::new()
.kind(RadrootsNostrKind::Custom(
u16::try_from(KIND_POST).expect("post kind must fit NIP-01"),
@@ -2769,7 +2768,7 @@ async fn fetch_relay_events_applies_shared_filter_limit_and_outcome_evidence() {
let skipped = signed_event_with_kind_and_hashtag("shared fetch skipped", KIND_POST, "soil");
let wrong_tag =
signed_event_with_kind_and_hashtag("shared fetch wrong tag", KIND_POST, "compost");
- let filter = radroots_nostr_filter_tag(
+ let filter = with_tag(
RadrootsNostrFilter::new()
.kind(RadrootsNostrKind::Custom(
u16::try_from(KIND_POST).expect("post kind must fit NIP-01"),
diff --git a/docs/api/radroots_nostr.txt b/docs/api/radroots_nostr.txt
@@ -1,236 +1,178 @@
pub mod radroots_nostr
pub mod radroots_nostr::blossom
-#[non_exhaustive] pub enum radroots_nostr::blossom::RadrootsNostrBlossomError
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::BlossomClaim(radroots_blossom::error::Error)
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::EmptyHeaderPayload
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::EventSigning
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::HeaderPaddingForbidden
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidEventId
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidEventJson
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidEventKind
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidEventKind::actual: u64
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidEventSignature
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidHeaderBase64
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidHeaderScheme
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidHeaderUtf8
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::InvalidHeaderWhitespace
-pub radroots_nostr::blossom::RadrootsNostrBlossomError::NonCanonicalHeaderBase64
-impl radroots_nostr::blossom::RadrootsNostrBlossomError
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomError::blossom_claim_error(&self) -> core::option::Option<&radroots_blossom::error::Error>
-pub const fn radroots_nostr::blossom::RadrootsNostrBlossomError::code(&self) -> &'static str
-impl core::convert::From<radroots_blossom::error::Error> for radroots_nostr::blossom::RadrootsNostrBlossomError
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomError::from(radroots_blossom::error::Error) -> Self
-impl core::error::Error for radroots_nostr::blossom::RadrootsNostrBlossomError
-impl core::fmt::Display for radroots_nostr::blossom::RadrootsNostrBlossomError
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomError::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub struct radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader(_)
-impl radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader::as_str(&self) -> &str
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader::into_string(self) -> alloc::string::String
-impl core::convert::AsRef<str> for radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader::as_ref(&self) -> &str
-impl core::fmt::Debug for radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader
-pub fn radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub struct radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization
-impl radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization
-pub fn radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization::author(&self) -> radroots_nostr::types::RadrootsNostrPublicKey
-pub fn radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization::created_at(&self) -> radroots_nostr::event::Timestamp
-pub fn radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization::event_id(&self) -> radroots_nostr::event::EventId
-impl core::fmt::Debug for radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization
-pub fn radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub struct radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization
-impl radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization
-pub fn radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization::author(&self) -> radroots_nostr::types::RadrootsNostrPublicKey
-pub fn radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization::claim(&self) -> &radroots_blossom::authorization::ValidatedAuthorizationClaim
-pub fn radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization::created_at(&self) -> radroots_nostr::event::Timestamp
-pub fn radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization::event_id(&self) -> radroots_nostr::event::EventId
-impl core::fmt::Debug for radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization
-pub fn radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub fn radroots_nostr::blossom::radroots_nostr_decode_verify_blossom_authorization_header(&str, &radroots_blossom::authorization::AuthorizationValidation) -> core::result::Result<radroots_nostr::blossom::RadrootsNostrVerifiedBlossomAuthorization, radroots_nostr::blossom::RadrootsNostrBlossomError>
-pub fn radroots_nostr::blossom::radroots_nostr_encode_blossom_authorization_header(&radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization) -> radroots_nostr::blossom::RadrootsNostrBlossomAuthorizationHeader
-pub fn radroots_nostr::blossom::radroots_nostr_sign_blossom_authorization(&radroots_nostr::types::RadrootsNostrKeys, &radroots_blossom::authorization::AuthoredUploadClaim) -> core::result::Result<radroots_nostr::blossom::RadrootsNostrSignedBlossomAuthorization, radroots_nostr::blossom::RadrootsNostrBlossomError>
-pub mod radroots_nostr::codec_adapters
-pub fn radroots_nostr::codec_adapters::to_job_feedback_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_feedback::JobFeedback>, radroots_event_codec::job::error::JobParseError>
-pub fn radroots_nostr::codec_adapters::to_job_feedback_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_feedback::JobFeedback>, radroots_event_codec::job::error::JobParseError>
-pub fn radroots_nostr::codec_adapters::to_job_request_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_request::JobRequest>, radroots_event_codec::job::error::JobParseError>
-pub fn radroots_nostr::codec_adapters::to_job_request_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_request::JobRequest>, radroots_event_codec::job::error::JobParseError>
-pub fn radroots_nostr::codec_adapters::to_job_result_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_result::JobResult>, radroots_event_codec::job::error::JobParseError>
-pub fn radroots_nostr::codec_adapters::to_job_result_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_result::JobResult>, radroots_event_codec::job::error::JobParseError>
-pub mod radroots_nostr::draft_signing
-pub fn radroots_nostr::draft_signing::radroots_nostr_sign_frozen_draft(&radroots_nostr::types::RadrootsNostrKeys, &radroots_event::draft::EventDraft) -> core::result::Result<radroots_event::draft::SignedEvent, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::error
-pub enum radroots_nostr::error::RadrootsNostrError
-pub radroots_nostr::error::RadrootsNostrError::CoordinateConversion
-pub radroots_nostr::error::RadrootsNostrError::DraftError(radroots_event::draft::DraftError)
-pub radroots_nostr::error::RadrootsNostrError::EventBuildError(nostr::event::builder::Error)
-pub radroots_nostr::error::RadrootsNostrError::EventConversion
-pub radroots_nostr::error::RadrootsNostrError::EventConversion::field: &'static str
-pub radroots_nostr::error::RadrootsNostrError::EventError(nostr::event::error::Error)
-pub radroots_nostr::error::RadrootsNostrError::EventWire(radroots_event::wire::v1::EventWireError)
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningAuthorMismatch
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningAuthorMismatch::actual: nostr::key::public_key::PublicKey
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningAuthorMismatch::expected: nostr::key::public_key::PublicKey
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningEventIdMismatch
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningEventIdMismatch::actual: nostr::event::id::EventId
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningEventIdMismatch::expected: nostr::event::id::EventId
-pub radroots_nostr::error::RadrootsNostrError::ExternalSigningEventInvalid(nostr::event::error::Error)
-pub radroots_nostr::error::RadrootsNostrError::FilterTagError(alloc::string::String)
-pub radroots_nostr::error::RadrootsNostrError::FoodAvailabilityEncode(radroots_event_codec::food_availability::authored::RadrootsFoodAvailabilityEncodeError)
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftEventIdMismatch
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftEventIdMismatch::actual_event_id: alloc::string::String
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftEventIdMismatch::expected_event_id: alloc::string::String
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftPubkeyMismatch
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftPubkeyMismatch::actual_pubkey: alloc::string::String
-pub radroots_nostr::error::RadrootsNostrError::FrozenDraftPubkeyMismatch::expected_pubkey: alloc::string::String
-pub radroots_nostr::error::RadrootsNostrError::InvalidEncryptedSecretKey
-pub radroots_nostr::error::RadrootsNostrError::InvalidNpub
-pub radroots_nostr::error::RadrootsNostrError::InvalidPublicKey
-pub radroots_nostr::error::RadrootsNostrError::InvalidSecretKey
-pub radroots_nostr::error::RadrootsNostrError::KeyError(nostr::key::Error)
-pub radroots_nostr::error::RadrootsNostrError::KindOutOfRange
-pub radroots_nostr::error::RadrootsNostrError::KindOutOfRange::kind: u32
-pub radroots_nostr::error::RadrootsNostrError::KindOutOfRange::max: u16
-pub radroots_nostr::error::RadrootsNostrError::ProfileEncode(radroots_event_codec::profile::authored::RadrootsAuthoredProfileEncodeError)
-pub radroots_nostr::error::RadrootsNostrError::SecretKeyDecryption
-pub radroots_nostr::error::RadrootsNostrError::SecretKeyEncryption
-pub radroots_nostr::error::RadrootsNostrError::SignedEvent(radroots_event::draft::SignedEventError)
-pub radroots_nostr::error::RadrootsNostrError::TagConversion
-pub radroots_nostr::error::RadrootsNostrError::TypedAuthoringRequired
-pub radroots_nostr::error::RadrootsNostrError::TypedAuthoringRequired::kind: u16
-impl core::convert::From<nostr::event::builder::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::event::builder::Error) -> Self
-impl core::convert::From<nostr::event::error::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::event::error::Error) -> Self
-impl core::convert::From<nostr::key::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::key::Error) -> Self
-pub enum radroots_nostr::error::RadrootsNostrTagsResolveError
-pub radroots_nostr::error::RadrootsNostrTagsResolveError::DecryptionError(alloc::string::String)
-pub radroots_nostr::error::RadrootsNostrTagsResolveError::MissingPTag(alloc::boxed::Box<nostr::event::Event>)
-pub radroots_nostr::error::RadrootsNostrTagsResolveError::NotRecipient
-pub radroots_nostr::error::RadrootsNostrTagsResolveError::ParseError(serde_json::error::Error)
+#[non_exhaustive] pub enum radroots_nostr::blossom::AuthorizationError
+pub radroots_nostr::blossom::AuthorizationError::BlossomClaim(radroots_blossom::error::Error)
+pub radroots_nostr::blossom::AuthorizationError::EmptyHeaderPayload
+pub radroots_nostr::blossom::AuthorizationError::EventSigning
+pub radroots_nostr::blossom::AuthorizationError::HeaderPaddingForbidden
+pub radroots_nostr::blossom::AuthorizationError::InvalidEventId
+pub radroots_nostr::blossom::AuthorizationError::InvalidEventJson
+pub radroots_nostr::blossom::AuthorizationError::InvalidEventKind
+pub radroots_nostr::blossom::AuthorizationError::InvalidEventKind::actual: u64
+pub radroots_nostr::blossom::AuthorizationError::InvalidEventSignature
+pub radroots_nostr::blossom::AuthorizationError::InvalidHeaderBase64
+pub radroots_nostr::blossom::AuthorizationError::InvalidHeaderScheme
+pub radroots_nostr::blossom::AuthorizationError::InvalidHeaderUtf8
+pub radroots_nostr::blossom::AuthorizationError::InvalidHeaderWhitespace
+pub radroots_nostr::blossom::AuthorizationError::NonCanonicalHeaderBase64
+impl radroots_nostr::blossom::AuthorizationError
+pub fn radroots_nostr::blossom::AuthorizationError::blossom_claim_error(&self) -> core::option::Option<&radroots_blossom::error::Error>
+pub const fn radroots_nostr::blossom::AuthorizationError::code(&self) -> &'static str
+impl core::convert::From<radroots_blossom::error::Error> for radroots_nostr::blossom::AuthorizationError
+pub fn radroots_nostr::blossom::AuthorizationError::from(radroots_blossom::error::Error) -> Self
+impl core::error::Error for radroots_nostr::blossom::AuthorizationError
+impl core::fmt::Display for radroots_nostr::blossom::AuthorizationError
+pub fn radroots_nostr::blossom::AuthorizationError::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub struct radroots_nostr::blossom::AuthorizationHeader(_)
+impl radroots_nostr::blossom::AuthorizationHeader
+pub fn radroots_nostr::blossom::AuthorizationHeader::as_str(&self) -> &str
+pub fn radroots_nostr::blossom::AuthorizationHeader::into_string(self) -> alloc::string::String
+impl core::convert::AsRef<str> for radroots_nostr::blossom::AuthorizationHeader
+pub fn radroots_nostr::blossom::AuthorizationHeader::as_ref(&self) -> &str
+impl core::fmt::Debug for radroots_nostr::blossom::AuthorizationHeader
+pub fn radroots_nostr::blossom::AuthorizationHeader::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub struct radroots_nostr::blossom::SignedAuthorization
+impl radroots_nostr::blossom::SignedAuthorization
+pub fn radroots_nostr::blossom::SignedAuthorization::author(&self) -> nostr::key::public_key::PublicKey
+pub fn radroots_nostr::blossom::SignedAuthorization::created_at(&self) -> radroots_nostr::event::Timestamp
+pub fn radroots_nostr::blossom::SignedAuthorization::event_id(&self) -> radroots_nostr::event::EventId
+impl core::fmt::Debug for radroots_nostr::blossom::SignedAuthorization
+pub fn radroots_nostr::blossom::SignedAuthorization::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub struct radroots_nostr::blossom::VerifiedAuthorization
+impl radroots_nostr::blossom::VerifiedAuthorization
+pub fn radroots_nostr::blossom::VerifiedAuthorization::author(&self) -> nostr::key::public_key::PublicKey
+pub fn radroots_nostr::blossom::VerifiedAuthorization::claim(&self) -> &radroots_blossom::authorization::ValidatedAuthorizationClaim
+pub fn radroots_nostr::blossom::VerifiedAuthorization::created_at(&self) -> radroots_nostr::event::Timestamp
+pub fn radroots_nostr::blossom::VerifiedAuthorization::event_id(&self) -> radroots_nostr::event::EventId
+impl core::fmt::Debug for radroots_nostr::blossom::VerifiedAuthorization
+pub fn radroots_nostr::blossom::VerifiedAuthorization::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub fn radroots_nostr::blossom::decode_verify_authorization_header(&str, &radroots_blossom::authorization::AuthorizationValidation) -> core::result::Result<radroots_nostr::blossom::VerifiedAuthorization, radroots_nostr::blossom::AuthorizationError>
+pub fn radroots_nostr::blossom::encode_authorization_header(&radroots_nostr::blossom::SignedAuthorization) -> radroots_nostr::blossom::AuthorizationHeader
+pub fn radroots_nostr::blossom::sign_authorization(&nostr::key::Keys, &radroots_blossom::authorization::AuthoredUploadClaim) -> core::result::Result<radroots_nostr::blossom::SignedAuthorization, radroots_nostr::blossom::AuthorizationError>
pub mod radroots_nostr::event
-pub struct radroots_nostr::event::RadrootsNostrExternalSigningRequest
-impl radroots_nostr::types::RadrootsNostrExternalSigningRequest
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::complete(self, radroots_nostr::event::Event) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::expected_event_id(&self) -> radroots_nostr::event::EventId
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::expected_public_key(&self) -> radroots_nostr::types::RadrootsNostrPublicKey
-impl serde_core::ser::Serialize for radroots_nostr::types::RadrootsNostrExternalSigningRequest
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer
-pub struct radroots_nostr::event::RadrootsNostrGenericEventBuilder
-impl radroots_nostr::types::RadrootsNostrGenericEventBuilder
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::allow_self_tagging(self) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::dedup_tags(self) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::into_external_signing_request(self, radroots_nostr::types::RadrootsNostrPublicKey) -> core::result::Result<radroots_nostr::types::RadrootsNostrExternalSigningRequest, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::new(radroots_nostr::event::Kind, impl core::convert::Into<alloc::string::String>) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::pow(self, u8) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::tag(self, radroots_nostr::tag::Tag) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::tags<I>(self, I) -> Self where I: core::iter::traits::collect::IntoIterator<Item = radroots_nostr::tag::Tag>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::text_note(impl core::convert::Into<alloc::string::String>) -> Self
-pub fn radroots_nostr::event::coordinate_from_nostr(&radroots_nostr::event::Coordinate) -> core::result::Result<radroots_event::id::Nip01Coordinate, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::event::coordinate_to_nostr(&radroots_event::id::Nip01Coordinate) -> core::result::Result<radroots_nostr::event::Coordinate, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::event::nostr_event_from_radroots(&radroots_event::envelope::EventEnvelope) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::event::radroots_event_from_nostr(&radroots_nostr::event::Event) -> core::result::Result<radroots_event::envelope::EventEnvelope, radroots_event::envelope::EventEnvelopeError>
-pub fn radroots_nostr::event::radroots_event_ptr_from_nostr(&radroots_nostr::event::Event) -> radroots_event::tag::EventPtr
+pub enum radroots_nostr::event::Verification
+pub radroots_nostr::event::Verification::IdMismatch
+pub radroots_nostr::event::Verification::IdVerified
+pub radroots_nostr::event::Verification::MalformedEnvelope
+pub radroots_nostr::event::Verification::SignatureInvalid
+pub radroots_nostr::event::Verification::Verified
+pub struct radroots_nostr::event::ApplicationHandlerSpec
+impl radroots_nostr::event::ApplicationHandlerSpec
+pub fn radroots_nostr::event::ApplicationHandlerSpec::extra_tags(&self) -> &[alloc::vec::Vec<alloc::string::String>]
+pub fn radroots_nostr::event::ApplicationHandlerSpec::identifier(&self) -> core::option::Option<&str>
+pub fn radroots_nostr::event::ApplicationHandlerSpec::kinds(&self) -> &[u32]
+pub fn radroots_nostr::event::ApplicationHandlerSpec::metadata(&self) -> core::option::Option<&radroots_nostr::event::Metadata>
+pub fn radroots_nostr::event::ApplicationHandlerSpec::new(alloc::vec::Vec<u32>) -> Self
+pub fn radroots_nostr::event::ApplicationHandlerSpec::nostr_connect_url(&self) -> core::option::Option<&str>
+pub fn radroots_nostr::event::ApplicationHandlerSpec::relays(&self) -> &[alloc::string::String]
+pub fn radroots_nostr::event::ApplicationHandlerSpec::with_extra_tags(self, alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>) -> Self
+pub fn radroots_nostr::event::ApplicationHandlerSpec::with_identifier(self, impl core::convert::Into<alloc::string::String>) -> Self
+pub fn radroots_nostr::event::ApplicationHandlerSpec::with_metadata(self, radroots_nostr::event::Metadata) -> Self
+pub fn radroots_nostr::event::ApplicationHandlerSpec::with_nostr_connect_url(self, impl core::convert::Into<alloc::string::String>) -> Self
+pub fn radroots_nostr::event::ApplicationHandlerSpec::with_relays(self, alloc::vec::Vec<alloc::string::String>) -> Self
+pub struct radroots_nostr::event::EventAdapter<'a>
+impl<'a> radroots_nostr::event::EventAdapter<'a>
+pub fn radroots_nostr::event::EventAdapter<'a>::new(&'a radroots_nostr::event::Event) -> Self
+impl radroots_event_codec::job::traits::JobEventLike for radroots_nostr::event::EventAdapter<'_>
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_author(&self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_content(&self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_id(&self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_kind(&self) -> u32
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_published_at(&self) -> u64
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_sig(&self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'_>::raw_tags(&self) -> alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>
+impl<'a> radroots_event_codec::job::traits::JobEventBorrow<'a> for radroots_nostr::event::EventAdapter<'a>
+pub fn radroots_nostr::event::EventAdapter<'a>::raw_author(&'a self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'a>::raw_content(&'a self) -> &'a str
+pub fn radroots_nostr::event::EventAdapter<'a>::raw_id(&'a self) -> alloc::string::String
+pub fn radroots_nostr::event::EventAdapter<'a>::raw_kind(&'a self) -> u32
+pub struct radroots_nostr::event::ExternalSigningRequest
+impl radroots_nostr::event::ExternalSigningRequest
+pub fn radroots_nostr::event::ExternalSigningRequest::complete(self, radroots_nostr::event::Event) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub fn radroots_nostr::event::ExternalSigningRequest::expected_event_id(&self) -> radroots_nostr::event::EventId
+pub fn radroots_nostr::event::ExternalSigningRequest::expected_public_key(&self) -> nostr::key::public_key::PublicKey
+impl serde_core::ser::Serialize for radroots_nostr::event::ExternalSigningRequest
+pub fn radroots_nostr::event::ExternalSigningRequest::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer
+pub struct radroots_nostr::event::FoodAvailabilityBuilder
+impl radroots_nostr::event::FoodAvailabilityBuilder
+pub fn radroots_nostr::event::FoodAvailabilityBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::GenericBuilder
+impl radroots_nostr::event::GenericBuilder
+pub fn radroots_nostr::event::GenericBuilder::allow_self_tagging(self) -> Self
+pub fn radroots_nostr::event::GenericBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::GenericBuilder::dedup_tags(self) -> Self
+pub fn radroots_nostr::event::GenericBuilder::into_external_signing_request(self, nostr::key::public_key::PublicKey) -> core::result::Result<radroots_nostr::event::ExternalSigningRequest, radroots_nostr::Error>
+pub fn radroots_nostr::event::GenericBuilder::new(radroots_nostr::event::Kind, impl core::convert::Into<alloc::string::String>) -> Self
+pub fn radroots_nostr::event::GenericBuilder::pow(self, u8) -> Self
+pub fn radroots_nostr::event::GenericBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub fn radroots_nostr::event::GenericBuilder::tag(self, radroots_nostr::tag::Tag) -> Self
+pub fn radroots_nostr::event::GenericBuilder::tags<I>(self, I) -> Self where I: core::iter::traits::collect::IntoIterator<Item = radroots_nostr::tag::Tag>
+pub fn radroots_nostr::event::GenericBuilder::text_note(impl core::convert::Into<alloc::string::String>) -> Self
+pub struct radroots_nostr::event::Nip09DeletionRequestBuilder
+impl radroots_nostr::event::Nip09DeletionRequestBuilder
+pub fn radroots_nostr::event::Nip09DeletionRequestBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::Nip09DeletionRequestBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::Nip10ReplyBuilder
+impl radroots_nostr::event::Nip10ReplyBuilder
+pub fn radroots_nostr::event::Nip10ReplyBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::Nip10ReplyBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::Nip22CommentBuilder
+impl radroots_nostr::event::Nip22CommentBuilder
+pub fn radroots_nostr::event::Nip22CommentBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::Nip22CommentBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::PostBuilder
+impl radroots_nostr::event::PostBuilder
+pub fn radroots_nostr::event::PostBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::PostBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::ProfileBuilder
+impl radroots_nostr::event::ProfileBuilder
+pub fn radroots_nostr::event::ProfileBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
+pub fn radroots_nostr::event::ProfileBuilder::sign_with_keys(self, &nostr::key::Keys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub struct radroots_nostr::event::SignatureVerifier
+impl radroots_event::verification::SignatureVerifier for radroots_nostr::event::SignatureVerifier
+pub fn radroots_nostr::event::SignatureVerifier::verify_signature(&self, &radroots_event::envelope::EventEnvelope) -> core::result::Result<(), radroots_event::verification::Error>
+pub fn radroots_nostr::event::build_application_handler(&radroots_nostr::event::ApplicationHandlerSpec) -> core::result::Result<radroots_nostr::event::GenericBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_ask(&radroots_event::post::AuthoredAsk) -> core::result::Result<radroots_nostr::event::PostBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_food_availability(&radroots_event::food::availability::FoodAvailabilityDetails, radroots_nostr::event::Timestamp) -> core::result::Result<radroots_nostr::event::FoodAvailabilityBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_job_feedback(&radroots_nostr::event::Event, &str, core::option::Option<alloc::string::String>, core::option::Option<alloc::vec::Vec<radroots_nostr::tag::Tag>>) -> core::result::Result<radroots_nostr::event::GenericBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_job_result(&radroots_nostr::event::Event, impl core::convert::Into<alloc::string::String>, u64, core::option::Option<alloc::string::String>, core::option::Option<alloc::vec::Vec<radroots_nostr::tag::Tag>>) -> core::result::Result<radroots_nostr::event::GenericBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_nip09_deletion_request(&radroots_event::post::deletion::AuthoredNip09DeletionRequest) -> core::result::Result<radroots_nostr::event::Nip09DeletionRequestBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_nip10_reply(&radroots_event::post::reply::AuthoredNip10Reply) -> core::result::Result<radroots_nostr::event::Nip10ReplyBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_nip22_comment(&radroots_event::post::comment::AuthoredNip22Comment) -> core::result::Result<radroots_nostr::event::Nip22CommentBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_photo_update(&radroots_event::post::AuthoredPhotoUpdate) -> core::result::Result<radroots_nostr::event::PostBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_profile(&radroots_event::profile::AuthoredProfile) -> core::result::Result<radroots_nostr::event::ProfileBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::build_update(&radroots_event::post::AuthoredUpdate) -> core::result::Result<radroots_nostr::event::PostBuilder, radroots_nostr::Error>
+pub fn radroots_nostr::event::coordinate_from_nostr(&radroots_nostr::event::Coordinate) -> core::result::Result<radroots_event::id::Nip01Coordinate, radroots_nostr::Error>
+pub fn radroots_nostr::event::coordinate_to_nostr(&radroots_event::id::Nip01Coordinate) -> core::result::Result<radroots_nostr::event::Coordinate, radroots_nostr::Error>
+pub fn radroots_nostr::event::created_at_u32_saturating(radroots_nostr::event::Timestamp) -> u32
+pub fn radroots_nostr::event::event_created_at_u32_saturating(&radroots_nostr::event::Event) -> u32
+pub fn radroots_nostr::event::from_nostr(&radroots_nostr::event::Event) -> core::result::Result<radroots_event::envelope::EventEnvelope, radroots_event::envelope::EventEnvelopeError>
+pub fn radroots_nostr::event::metadata_has_fields(&radroots_nostr::event::Metadata) -> bool
+pub fn radroots_nostr::event::pointer_from_nostr(&radroots_nostr::event::Event) -> radroots_event::tag::EventPtr
+pub fn radroots_nostr::event::post_filter(core::option::Option<u16>, core::option::Option<u64>) -> radroots_nostr::filter::Filter
+pub fn radroots_nostr::event::to_job_feedback_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_feedback::JobFeedback>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_job_feedback_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_feedback::JobFeedback>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_job_request_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_request::JobRequest>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_job_request_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_request::JobRequest>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_job_result_index(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedEvent<radroots_event::social::job_result::JobResult>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_job_result_metadata(&radroots_nostr::event::Event) -> core::result::Result<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::job_result::JobResult>, radroots_event_codec::job::error::JobParseError>
+pub fn radroots_nostr::event::to_nostr(&radroots_event::envelope::EventEnvelope) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::Error>
+pub fn radroots_nostr::event::to_post_event_metadata(&radroots_nostr::event::Event) -> radroots_event_codec::parsed::RadrootsParsedData<radroots_event_codec::post::decode::LegacyPost>
+pub fn radroots_nostr::event::to_profile_event_metadata(&radroots_nostr::event::Event) -> core::option::Option<radroots_event_codec::parsed::RadrootsParsedData<radroots_event_codec::profile::RadrootsProfileData>>
+pub fn radroots_nostr::event::verify(&radroots_event::envelope::EventEnvelope) -> radroots_nostr::event::Verification
+pub fn radroots_nostr::event::verify_id(&radroots_event::envelope::EventEnvelope) -> radroots_nostr::event::Verification
pub type radroots_nostr::event::Coordinate = nostr::nips::nip01::Coordinate
pub type radroots_nostr::event::Event = nostr::event::Event
pub type radroots_nostr::event::EventId = nostr::event::id::EventId
pub type radroots_nostr::event::Kind = nostr::event::kind::Kind
pub type radroots_nostr::event::Metadata = nostr::nips::nip01::Metadata
pub type radroots_nostr::event::Timestamp = nostr::types::time::Timestamp
-pub mod radroots_nostr::event_adapters
-pub fn radroots_nostr::event_adapters::to_post_event_metadata(&radroots_nostr::event::Event) -> radroots_event_codec::parsed::RadrootsParsedData<radroots_event_codec::post::decode::LegacyPost>
-pub fn radroots_nostr::event_adapters::to_profile_event_metadata(&radroots_nostr::event::Event) -> core::option::Option<radroots_event_codec::parsed::RadrootsParsedData<radroots_event_codec::profile::RadrootsProfileData>>
-pub mod radroots_nostr::event_verify
-pub enum radroots_nostr::event_verify::RadrootsNostrEventVerification
-pub radroots_nostr::event_verify::RadrootsNostrEventVerification::IdMismatch
-pub radroots_nostr::event_verify::RadrootsNostrEventVerification::IdVerified
-pub radroots_nostr::event_verify::RadrootsNostrEventVerification::MalformedEnvelope
-pub radroots_nostr::event_verify::RadrootsNostrEventVerification::SignatureInvalid
-pub radroots_nostr::event_verify::RadrootsNostrEventVerification::Verified
-pub struct radroots_nostr::event_verify::NostrSignatureVerifier
-impl radroots_event::verification::SignatureVerifier for radroots_nostr::event_verify::NostrSignatureVerifier
-pub fn radroots_nostr::event_verify::NostrSignatureVerifier::verify_signature(&self, &radroots_event::envelope::EventEnvelope) -> core::result::Result<(), radroots_event::verification::Error>
-pub fn radroots_nostr::event_verify::radroots_nostr_verify_event(&radroots_event::envelope::EventEnvelope) -> radroots_nostr::event_verify::RadrootsNostrEventVerification
-pub fn radroots_nostr::event_verify::radroots_nostr_verify_event_id(&radroots_event::envelope::EventEnvelope) -> radroots_nostr::event_verify::RadrootsNostrEventVerification
-pub mod radroots_nostr::events
-pub mod radroots_nostr::events::application_handler
-pub struct radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::extra_tags: alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::identifier: core::option::Option<alloc::string::String>
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::kinds: alloc::vec::Vec<u32>
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::metadata: core::option::Option<radroots_nostr::event::Metadata>
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::nostrconnect_url: core::option::Option<alloc::string::String>
-pub radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::relays: alloc::vec::Vec<alloc::string::String>
-impl radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec
-pub fn radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec::new(alloc::vec::Vec<u32>) -> Self
-pub fn radroots_nostr::events::application_handler::radroots_nostr_build_application_handler_event(&radroots_nostr::events::application_handler::RadrootsNostrApplicationHandlerSpec) -> core::result::Result<radroots_nostr::types::RadrootsNostrGenericEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::application_handler::radroots_nostr_metadata_has_fields(&radroots_nostr::event::Metadata) -> bool
-pub mod radroots_nostr::events::comment
-pub struct radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder
-impl radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder
-pub fn radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::comment::radroots_nostr_build_nip22_comment_event(&radroots_event::post::comment::AuthoredNip22Comment) -> core::result::Result<radroots_nostr::events::comment::RadrootsNostrNip22CommentEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::events::deletion
-pub struct radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder
-impl radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder
-pub fn radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::deletion::radroots_nostr_build_nip09_deletion_request_event(&radroots_event::post::deletion::AuthoredNip09DeletionRequest) -> core::result::Result<radroots_nostr::events::deletion::RadrootsNostrNip09DeletionRequestEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::events::food_availability
-pub struct radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder
-impl radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder
-pub fn radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::food_availability::radroots_nostr_build_food_availability_event(&radroots_event::food::availability::FoodAvailabilityDetails, radroots_nostr::event::Timestamp) -> core::result::Result<radroots_nostr::events::food_availability::RadrootsNostrFoodAvailabilityEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::events::jobs
-pub fn radroots_nostr::events::jobs::radroots_nostr_build_event_job_feedback(&radroots_nostr::event::Event, &str, core::option::Option<alloc::string::String>, core::option::Option<alloc::vec::Vec<radroots_nostr::tag::Tag>>) -> core::result::Result<radroots_nostr::types::RadrootsNostrGenericEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::jobs::radroots_nostr_build_event_job_result(&radroots_nostr::event::Event, impl core::convert::Into<alloc::string::String>, u64, core::option::Option<alloc::string::String>, core::option::Option<alloc::vec::Vec<radroots_nostr::tag::Tag>>) -> core::result::Result<radroots_nostr::types::RadrootsNostrGenericEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::events::metadata
-pub struct radroots_nostr::events::metadata::RadrootsNostrProfileEventBuilder
-impl radroots_nostr::events::metadata::RadrootsNostrProfileEventBuilder
-pub fn radroots_nostr::events::metadata::RadrootsNostrProfileEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::events::metadata::RadrootsNostrProfileEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::metadata::radroots_nostr_build_profile_event(&radroots_event::profile::AuthoredProfile) -> core::result::Result<radroots_nostr::events::metadata::RadrootsNostrProfileEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub mod radroots_nostr::events::post
-pub struct radroots_nostr::events::post::RadrootsNostrPostEventBuilder
-impl radroots_nostr::events::post::RadrootsNostrPostEventBuilder
-pub fn radroots_nostr::events::post::RadrootsNostrPostEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::events::post::RadrootsNostrPostEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::post::radroots_nostr_build_ask_event(&radroots_event::post::AuthoredAsk) -> core::result::Result<radroots_nostr::events::post::RadrootsNostrPostEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::post::radroots_nostr_build_photo_update_event(&radroots_event::post::AuthoredPhotoUpdate) -> core::result::Result<radroots_nostr::events::post::RadrootsNostrPostEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::post::radroots_nostr_build_update_event(&radroots_event::post::AuthoredUpdate) -> core::result::Result<radroots_nostr::events::post::RadrootsNostrPostEventBuilder, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::post::radroots_nostr_post_events_filter(core::option::Option<u16>, core::option::Option<u64>) -> radroots_nostr::filter::Filter
-pub mod radroots_nostr::events::reply
-pub struct radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder
-impl radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder
-pub fn radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::events::reply::radroots_nostr_build_nip10_reply_event(&radroots_event::post::reply::AuthoredNip10Reply) -> core::result::Result<radroots_nostr::events::reply::RadrootsNostrNip10ReplyEventBuilder, radroots_nostr::error::RadrootsNostrError>
pub mod radroots_nostr::filter
-pub fn radroots_nostr::filter::radroots_nostr_filter_kind(u16) -> radroots_nostr::filter::Filter
-pub fn radroots_nostr::filter::radroots_nostr_filter_new_events(radroots_nostr::filter::Filter) -> radroots_nostr::filter::Filter
-pub fn radroots_nostr::filter::radroots_nostr_filter_tag(radroots_nostr::filter::Filter, &str, alloc::vec::Vec<alloc::string::String>) -> core::result::Result<radroots_nostr::filter::Filter, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::filter::radroots_nostr_kind(u16) -> radroots_nostr::event::Kind
+pub fn radroots_nostr::filter::for_kind(u16) -> radroots_nostr::filter::Filter
+pub fn radroots_nostr::filter::kind(u16) -> radroots_nostr::event::Kind
+pub fn radroots_nostr::filter::since_now(radroots_nostr::filter::Filter) -> radroots_nostr::filter::Filter
+pub fn radroots_nostr::filter::with_tag(radroots_nostr::filter::Filter, &str, alloc::vec::Vec<alloc::string::String>) -> core::result::Result<radroots_nostr::filter::Filter, radroots_nostr::Error>
pub type radroots_nostr::filter::Filter = nostr::filter::Filter
-pub mod radroots_nostr::job_adapter
-pub struct radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>
-impl<'a> radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>::new(&'a radroots_nostr::event::Event) -> Self
-impl radroots_event_codec::job::traits::JobEventLike for radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_author(&self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_content(&self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_id(&self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_kind(&self) -> u32
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_published_at(&self) -> u64
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_sig(&self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'_>::raw_tags(&self) -> alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>
-impl<'a> radroots_event_codec::job::traits::JobEventBorrow<'a> for radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>::raw_author(&'a self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>::raw_content(&'a self) -> &'a str
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>::raw_id(&'a self) -> alloc::string::String
-pub fn radroots_nostr::job_adapter::RadrootsNostrEventAdapter<'a>::raw_kind(&'a self) -> u32
pub mod radroots_nostr::key
pub enum radroots_nostr::key::Nip49KeySecurity
pub radroots_nostr::key::Nip49KeySecurity::Medium
@@ -248,120 +190,98 @@ pub fn radroots_nostr::key::Nip49Options::default() -> Self
pub struct radroots_nostr::key::SecretKey
impl radroots_nostr::key::SecretKey
pub fn radroots_nostr::key::SecretKey::generate() -> Self
-pub fn radroots_nostr::key::SecretKey::parse(&str) -> core::result::Result<Self, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::SecretKey::public_key(&self) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::error::RadrootsNostrError>
+pub fn radroots_nostr::key::SecretKey::parse(&str) -> core::result::Result<Self, radroots_nostr::Error>
+pub fn radroots_nostr::key::SecretKey::public_key(&self) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::Error>
impl core::fmt::Debug for radroots_nostr::key::SecretKey
pub fn radroots_nostr::key::SecretKey::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub fn radroots_nostr::key::decrypt_secret_key_nip49(&str, &str) -> core::result::Result<radroots_nostr::key::SecretKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::encrypt_secret_key_nip49(&radroots_nostr::key::SecretKey, &str) -> core::result::Result<alloc::string::String, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::encrypt_secret_key_nip49_with_options(&radroots_nostr::key::SecretKey, &str, radroots_nostr::key::Nip49Options) -> core::result::Result<alloc::string::String, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::parse_public_key(&str) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::parse_secret_key(&str) -> core::result::Result<radroots_nostr::key::SecretKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::public_key_from_nostr(nostr::key::public_key::PublicKey) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::public_key_from_npub(&str) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::public_key_to_nostr(radroots_identity::key::PublicKey) -> core::result::Result<nostr::key::public_key::PublicKey, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::key::public_key_to_npub(radroots_identity::key::PublicKey) -> core::result::Result<alloc::string::String, radroots_nostr::error::RadrootsNostrError>
+pub fn radroots_nostr::key::decrypt_secret_key_nip49(&str, &str) -> core::result::Result<radroots_nostr::key::SecretKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::encrypt_secret_key_nip49(&radroots_nostr::key::SecretKey, &str) -> core::result::Result<alloc::string::String, radroots_nostr::Error>
+pub fn radroots_nostr::key::encrypt_secret_key_nip49_with_options(&radroots_nostr::key::SecretKey, &str, radroots_nostr::key::Nip49Options) -> core::result::Result<alloc::string::String, radroots_nostr::Error>
+pub fn radroots_nostr::key::parse_public_key(&str) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::parse_secret_key(&str) -> core::result::Result<radroots_nostr::key::SecretKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::public_key_from_nostr(nostr::key::public_key::PublicKey) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::public_key_from_npub(&str) -> core::result::Result<radroots_identity::key::PublicKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::public_key_to_nostr(radroots_identity::key::PublicKey) -> core::result::Result<nostr::key::public_key::PublicKey, radroots_nostr::Error>
+pub fn radroots_nostr::key::public_key_to_npub(radroots_identity::key::PublicKey) -> core::result::Result<alloc::string::String, radroots_nostr::Error>
pub fn radroots_nostr::key::secret_key_to_nsec(&radroots_nostr::key::SecretKey) -> alloc::string::String
pub mod radroots_nostr::nip17
-#[non_exhaustive] pub enum radroots_nostr::nip17::RadrootsNip17Error
-pub radroots_nostr::nip17::RadrootsNip17Error::GiftWrap
-pub radroots_nostr::nip17::RadrootsNip17Error::InvalidRecipient
-pub radroots_nostr::nip17::RadrootsNip17Error::MessageDecode
-pub radroots_nostr::nip17::RadrootsNip17Error::MessageEncode
-pub radroots_nostr::nip17::RadrootsNip17Error::Signer
-pub radroots_nostr::nip17::RadrootsNip17Error::UnsupportedRumorKind
-pub radroots_nostr::nip17::RadrootsNip17Error::UnsupportedRumorKind::kind: u32
-impl radroots_nostr::nip17::RadrootsNip17Error
-pub const fn radroots_nostr::nip17::RadrootsNip17Error::code(&self) -> &'static str
-impl core::convert::From<nostr::event::builder::Error> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(nostr::event::builder::Error) -> Self
-impl core::convert::From<nostr::key::Error> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(nostr::key::Error) -> Self
-impl core::convert::From<nostr::nips::nip59::Error> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(nostr::nips::nip59::Error) -> Self
-impl core::convert::From<nostr::signer::SignerError> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(nostr::signer::SignerError) -> Self
-impl core::convert::From<radroots_event_codec::error::EventEncodeError> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(radroots_event_codec::error::EventEncodeError) -> Self
-impl core::convert::From<radroots_event_codec::error::EventParseError> for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::from(radroots_event_codec::error::EventParseError) -> Self
-impl core::error::Error for radroots_nostr::nip17::RadrootsNip17Error
-impl core::fmt::Display for radroots_nostr::nip17::RadrootsNip17Error
-pub fn radroots_nostr::nip17::RadrootsNip17Error::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub enum radroots_nostr::nip17::RadrootsNip17Rumor
-pub radroots_nostr::nip17::RadrootsNip17Rumor::Message(radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::message::Message>)
-pub radroots_nostr::nip17::RadrootsNip17Rumor::MessageFile(alloc::boxed::Box<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::message_file::MessageFile>>)
-impl core::fmt::Debug for radroots_nostr::nip17::RadrootsNip17Rumor
-pub fn radroots_nostr::nip17::RadrootsNip17Rumor::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-pub struct radroots_nostr::nip17::RadrootsNip17WrapOptions
-pub radroots_nostr::nip17::RadrootsNip17WrapOptions::gift_wrap_tags: alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>
-pub radroots_nostr::nip17::RadrootsNip17WrapOptions::include_sender: bool
-pub radroots_nostr::nip17::RadrootsNip17WrapOptions::rumor_created_at: core::option::Option<u64>
-impl core::default::Default for radroots_nostr::nip17::RadrootsNip17WrapOptions
-pub fn radroots_nostr::nip17::RadrootsNip17WrapOptions::default() -> Self
-pub async fn radroots_nostr::nip17::radroots_nostr_unwrap_gift_wrap<T>(&T, &nostr::event::Event) -> core::result::Result<radroots_nostr::nip17::RadrootsNip17Rumor, radroots_nostr::nip17::RadrootsNip17Error> where T: nostr::signer::NostrSigner
-pub async fn radroots_nostr::nip17::radroots_nostr_wrap_message<T>(&T, &radroots_event::social::message::Message, radroots_nostr::nip17::RadrootsNip17WrapOptions) -> core::result::Result<alloc::vec::Vec<nostr::event::Event>, radroots_nostr::nip17::RadrootsNip17Error> where T: nostr::signer::NostrSigner
-pub async fn radroots_nostr::nip17::radroots_nostr_wrap_message_file<T>(&T, &radroots_event::social::message_file::MessageFile, radroots_nostr::nip17::RadrootsNip17WrapOptions) -> core::result::Result<alloc::vec::Vec<nostr::event::Event>, radroots_nostr::nip17::RadrootsNip17Error> where T: nostr::signer::NostrSigner
+#[non_exhaustive] pub enum radroots_nostr::nip17::Error
+pub radroots_nostr::nip17::Error::GiftWrap
+pub radroots_nostr::nip17::Error::InvalidRecipient
+pub radroots_nostr::nip17::Error::MessageDecode
+pub radroots_nostr::nip17::Error::MessageEncode
+pub radroots_nostr::nip17::Error::Signer
+pub radroots_nostr::nip17::Error::UnsupportedRumorKind
+pub radroots_nostr::nip17::Error::UnsupportedRumorKind::kind: u32
+impl radroots_nostr::nip17::Error
+pub const fn radroots_nostr::nip17::Error::code(&self) -> &'static str
+impl core::convert::From<nostr::event::builder::Error> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(nostr::event::builder::Error) -> Self
+impl core::convert::From<nostr::key::Error> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(nostr::key::Error) -> Self
+impl core::convert::From<nostr::nips::nip59::Error> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(nostr::nips::nip59::Error) -> Self
+impl core::convert::From<nostr::signer::SignerError> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(nostr::signer::SignerError) -> Self
+impl core::convert::From<radroots_event_codec::error::EventEncodeError> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(radroots_event_codec::error::EventEncodeError) -> Self
+impl core::convert::From<radroots_event_codec::error::EventParseError> for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::from(radroots_event_codec::error::EventParseError) -> Self
+impl core::error::Error for radroots_nostr::nip17::Error
+impl core::fmt::Display for radroots_nostr::nip17::Error
+pub fn radroots_nostr::nip17::Error::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub enum radroots_nostr::nip17::Rumor
+pub radroots_nostr::nip17::Rumor::Message(radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::message::Message>)
+pub radroots_nostr::nip17::Rumor::MessageFile(alloc::boxed::Box<radroots_event_codec::parsed::RadrootsParsedData<radroots_event::social::message_file::MessageFile>>)
+impl core::fmt::Debug for radroots_nostr::nip17::Rumor
+pub fn radroots_nostr::nip17::Rumor::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+pub struct radroots_nostr::nip17::WrapOptions
+impl radroots_nostr::nip17::WrapOptions
+pub fn radroots_nostr::nip17::WrapOptions::gift_wrap_tags(&self) -> &[alloc::vec::Vec<alloc::string::String>]
+pub fn radroots_nostr::nip17::WrapOptions::include_sender(self, bool) -> Self
+pub const fn radroots_nostr::nip17::WrapOptions::includes_sender(&self) -> bool
+pub const fn radroots_nostr::nip17::WrapOptions::rumor_created_at(&self) -> core::option::Option<u64>
+pub fn radroots_nostr::nip17::WrapOptions::with_gift_wrap_tags(self, alloc::vec::Vec<alloc::vec::Vec<alloc::string::String>>) -> Self
+pub fn radroots_nostr::nip17::WrapOptions::with_rumor_created_at(self, u64) -> Self
+impl core::default::Default for radroots_nostr::nip17::WrapOptions
+pub fn radroots_nostr::nip17::WrapOptions::default() -> Self
+pub async fn radroots_nostr::nip17::unwrap_gift_wrap<T>(&T, &nostr::event::Event) -> core::result::Result<radroots_nostr::nip17::Rumor, radroots_nostr::nip17::Error> where T: nostr::signer::NostrSigner
+pub async fn radroots_nostr::nip17::wrap_message<T>(&T, &radroots_event::social::message::Message, radroots_nostr::nip17::WrapOptions) -> core::result::Result<alloc::vec::Vec<nostr::event::Event>, radroots_nostr::nip17::Error> where T: nostr::signer::NostrSigner
+pub async fn radroots_nostr::nip17::wrap_message_file<T>(&T, &radroots_event::social::message_file::MessageFile, radroots_nostr::nip17::WrapOptions) -> core::result::Result<alloc::vec::Vec<nostr::event::Event>, radroots_nostr::nip17::Error> where T: nostr::signer::NostrSigner
pub mod radroots_nostr::signing
pub struct radroots_nostr::signing::LocalSigner
impl radroots_nostr::signing::LocalSigner
-pub fn radroots_nostr::signing::LocalSigner::generate() -> core::result::Result<Self, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::signing::LocalSigner::new(radroots_nostr::key::SecretKey) -> core::result::Result<Self, radroots_nostr::error::RadrootsNostrError>
+pub fn radroots_nostr::signing::LocalSigner::generate() -> core::result::Result<Self, radroots_nostr::Error>
+pub fn radroots_nostr::signing::LocalSigner::new(radroots_nostr::key::SecretKey) -> core::result::Result<Self, radroots_nostr::Error>
pub const fn radroots_nostr::signing::LocalSigner::public_key(&self) -> radroots_identity::key::PublicKey
impl core::fmt::Debug for radroots_nostr::signing::LocalSigner
pub fn radroots_nostr::signing::LocalSigner::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl radroots_signing::signer::Signer for radroots_nostr::signing::LocalSigner
pub fn radroots_nostr::signing::LocalSigner::sign(&self, radroots_signing::request::SignRequest) -> radroots_signing::signer::BoxFuture<'_, core::result::Result<radroots_signing::receipt::SignReceipt, radroots_signing::error::Error>>
pub fn radroots_nostr::signing::LocalSigner::status(&self) -> radroots_signing::signer::BoxFuture<'_, core::result::Result<radroots_signing::status::SignerStatus, radroots_signing::error::Error>>
+pub fn radroots_nostr::signing::sign_frozen_draft(&nostr::key::Keys, &radroots_event::draft::EventDraft) -> core::result::Result<radroots_event::draft::SignedEvent, radroots_nostr::Error>
pub mod radroots_nostr::tag
-pub fn radroots_nostr::tag::from_parts(alloc::vec::Vec<alloc::string::String>) -> core::result::Result<radroots_nostr::tag::Tag, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::tag::radroots_nostr_tag_at_value(&radroots_nostr::tag::Tag, usize) -> core::option::Option<alloc::string::String>
-pub fn radroots_nostr::tag::radroots_nostr_tag_first_value(&radroots_nostr::tag::Tag, &str) -> core::option::Option<alloc::string::String>
-pub fn radroots_nostr::tag::radroots_nostr_tag_match_geohash(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
-pub fn radroots_nostr::tag::radroots_nostr_tag_match_l(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, f64)>
-pub fn radroots_nostr::tag::radroots_nostr_tag_match_location(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, &str, &str)>
-pub fn radroots_nostr::tag::radroots_nostr_tag_match_summary(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
-pub fn radroots_nostr::tag::radroots_nostr_tag_match_title(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
-pub fn radroots_nostr::tag::radroots_nostr_tag_relays_parse(&radroots_nostr::tag::Tag) -> core::option::Option<&alloc::vec::Vec<radroots_nostr::types::RadrootsNostrRelayUrl>>
-pub fn radroots_nostr::tag::radroots_nostr_tag_slice(&radroots_nostr::tag::Tag, usize) -> core::option::Option<alloc::vec::Vec<alloc::string::String>>
-pub fn radroots_nostr::tag::radroots_nostr_tags_match(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, &[alloc::string::String])>
-pub fn radroots_nostr::tag::radroots_nostr_tags_resolve(&radroots_nostr::event::Event, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<alloc::vec::Vec<radroots_nostr::tag::Tag>, radroots_nostr::error::RadrootsNostrTagsResolveError>
+pub enum radroots_nostr::tag::ResolveError
+pub radroots_nostr::tag::ResolveError::DecryptionError(alloc::string::String)
+pub radroots_nostr::tag::ResolveError::MissingPTag(alloc::boxed::Box<nostr::event::Event>)
+pub radroots_nostr::tag::ResolveError::NotRecipient
+pub radroots_nostr::tag::ResolveError::ParseError(serde_json::error::Error)
+pub fn radroots_nostr::tag::first_value(&radroots_nostr::tag::Tag, &str) -> core::option::Option<alloc::string::String>
+pub fn radroots_nostr::tag::from_parts(alloc::vec::Vec<alloc::string::String>) -> core::result::Result<radroots_nostr::tag::Tag, radroots_nostr::Error>
+pub fn radroots_nostr::tag::match_geohash(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
+pub fn radroots_nostr::tag::match_location(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, &str, &str)>
+pub fn radroots_nostr::tag::match_location_coordinate(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, f64)>
+pub fn radroots_nostr::tag::match_parts(&radroots_nostr::tag::Tag) -> core::option::Option<(&str, &[alloc::string::String])>
+pub fn radroots_nostr::tag::match_summary(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
+pub fn radroots_nostr::tag::match_title(&radroots_nostr::tag::Tag) -> core::option::Option<alloc::string::String>
+pub fn radroots_nostr::tag::relay_urls(&radroots_nostr::tag::Tag) -> core::option::Option<&alloc::vec::Vec<nostr::types::url::RelayUrl>>
+pub fn radroots_nostr::tag::resolve(&radroots_nostr::event::Event, &nostr::key::Keys) -> core::result::Result<alloc::vec::Vec<radroots_nostr::tag::Tag>, radroots_nostr::tag::ResolveError>
pub fn radroots_nostr::tag::to_parts(&radroots_nostr::tag::Tag) -> alloc::vec::Vec<alloc::string::String>
+pub fn radroots_nostr::tag::value_at(&radroots_nostr::tag::Tag, usize) -> core::option::Option<alloc::string::String>
+pub fn radroots_nostr::tag::values_from(&radroots_nostr::tag::Tag, usize) -> core::option::Option<alloc::vec::Vec<alloc::string::String>>
pub type radroots_nostr::tag::Tag = nostr::event::tag::Tag
pub type radroots_nostr::tag::TagKind<'a> = nostr::event::tag::kind::TagKind<'a>
pub type radroots_nostr::tag::TagStandard = nostr::event::tag::standard::TagStandard
-pub mod radroots_nostr::types
-pub use radroots_nostr::types::RadrootsNostrFromBech32
-pub use radroots_nostr::types::RadrootsNostrSecp256k1SecretKey
-pub use radroots_nostr::types::RadrootsNostrToBech32
-pub struct radroots_nostr::types::RadrootsNostrExternalSigningRequest
-impl radroots_nostr::types::RadrootsNostrExternalSigningRequest
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::complete(self, radroots_nostr::event::Event) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::expected_event_id(&self) -> radroots_nostr::event::EventId
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::expected_public_key(&self) -> radroots_nostr::types::RadrootsNostrPublicKey
-impl serde_core::ser::Serialize for radroots_nostr::types::RadrootsNostrExternalSigningRequest
-pub fn radroots_nostr::types::RadrootsNostrExternalSigningRequest::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer
-pub struct radroots_nostr::types::RadrootsNostrGenericEventBuilder
-impl radroots_nostr::types::RadrootsNostrGenericEventBuilder
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::allow_self_tagging(self) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::custom_created_at(self, radroots_nostr::event::Timestamp) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::dedup_tags(self) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::into_external_signing_request(self, radroots_nostr::types::RadrootsNostrPublicKey) -> core::result::Result<radroots_nostr::types::RadrootsNostrExternalSigningRequest, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::new(radroots_nostr::event::Kind, impl core::convert::Into<alloc::string::String>) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::pow(self, u8) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::sign_with_keys(self, &radroots_nostr::types::RadrootsNostrKeys) -> core::result::Result<radroots_nostr::event::Event, radroots_nostr::error::RadrootsNostrError>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::tag(self, radroots_nostr::tag::Tag) -> Self
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::tags<I>(self, I) -> Self where I: core::iter::traits::collect::IntoIterator<Item = radroots_nostr::tag::Tag>
-pub fn radroots_nostr::types::RadrootsNostrGenericEventBuilder::text_note(impl core::convert::Into<alloc::string::String>) -> Self
-pub type radroots_nostr::types::RadrootsNostrKeys = nostr::key::Keys
-pub type radroots_nostr::types::RadrootsNostrPublicKey = nostr::key::public_key::PublicKey
-pub type radroots_nostr::types::RadrootsNostrRelayUrl = nostr::types::url::RelayUrl
-pub type radroots_nostr::types::RadrootsNostrSecretKey = nostr::key::secret_key::SecretKey
-pub type radroots_nostr::types::RadrootsNostrSubscriptionId = nostr::message::SubscriptionId
-pub type radroots_nostr::types::RadrootsNostrUrl = url::Url
-pub mod radroots_nostr::util
-pub fn radroots_nostr::util::created_at_u32_saturating(radroots_nostr::event::Timestamp) -> u32
-pub fn radroots_nostr::util::event_created_at_u32_saturating(&radroots_nostr::event::Event) -> u32
pub enum radroots_nostr::Error
pub radroots_nostr::Error::CoordinateConversion
pub radroots_nostr::Error::DraftError(radroots_event::draft::DraftError)
@@ -400,9 +320,9 @@ pub radroots_nostr::Error::SignedEvent(radroots_event::draft::SignedEventError)
pub radroots_nostr::Error::TagConversion
pub radroots_nostr::Error::TypedAuthoringRequired
pub radroots_nostr::Error::TypedAuthoringRequired::kind: u16
-impl core::convert::From<nostr::event::builder::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::event::builder::Error) -> Self
-impl core::convert::From<nostr::event::error::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::event::error::Error) -> Self
-impl core::convert::From<nostr::key::Error> for radroots_nostr::error::RadrootsNostrError
-pub fn radroots_nostr::error::RadrootsNostrError::from(nostr::key::Error) -> Self
+impl core::convert::From<nostr::event::builder::Error> for radroots_nostr::Error
+pub fn radroots_nostr::Error::from(nostr::event::builder::Error) -> Self
+impl core::convert::From<nostr::event::error::Error> for radroots_nostr::Error
+pub fn radroots_nostr::Error::from(nostr::event::error::Error) -> Self
+impl core::convert::From<nostr::key::Error> for radroots_nostr::Error
+pub fn radroots_nostr::Error::from(nostr::key::Error) -> Self
diff --git a/tools/xtask/src/contract.rs b/tools/xtask/src/contract.rs
@@ -1903,8 +1903,8 @@ const REPLY_WITNESSES: [EventBoundarySourceWitness; 5] = [
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/events/reply.rs",
required_fragments: &[
- "pub struct RadrootsNostrNip10ReplyEventBuilder",
- "pub fn radroots_nostr_build_nip10_reply_event",
+ "pub struct Nip10ReplyBuilder",
+ "pub fn build_nip10_reply_event",
],
},
];
@@ -1943,8 +1943,8 @@ const COMMENT_WITNESSES: [EventBoundarySourceWitness; 7] = [
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/events/comment.rs",
required_fragments: &[
- "pub struct RadrootsNostrNip22CommentEventBuilder",
- "pub fn radroots_nostr_build_nip22_comment_event",
+ "pub struct Nip22CommentBuilder",
+ "pub fn build_nip22_comment_event",
],
},
EventBoundarySourceWitness {
@@ -1990,8 +1990,8 @@ const DELETION_WITNESSES: [EventBoundarySourceWitness; 7] = [
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/events/deletion.rs",
required_fragments: &[
- "pub struct RadrootsNostrNip09DeletionRequestEventBuilder",
- "pub fn radroots_nostr_build_nip09_deletion_request_event",
+ "pub struct Nip09DeletionRequestBuilder",
+ "pub fn build_nip09_deletion_request_event",
],
},
EventBoundarySourceWitness {
@@ -2055,10 +2055,7 @@ const MESSAGE_WITNESSES: [EventBoundarySourceWitness; 4] = [
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/nip17.rs",
- required_fragments: &[
- "pub async fn radroots_nostr_wrap_message<T>(",
- "KIND_MESSAGE =>",
- ],
+ required_fragments: &["pub async fn wrap_message<T>(", "KIND_MESSAGE =>"],
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/lib.rs",
@@ -2077,10 +2074,7 @@ const MESSAGE_FILE_WITNESSES: [EventBoundarySourceWitness; 4] = [
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/nip17.rs",
- required_fragments: &[
- "pub async fn radroots_nostr_wrap_message_file<T>(",
- "KIND_MESSAGE_FILE =>",
- ],
+ required_fragments: &["pub async fn wrap_message_file<T>(", "KIND_MESSAGE_FILE =>"],
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/lib.rs",
@@ -2099,7 +2093,7 @@ const GIFT_WRAP_WITNESSES: [EventBoundarySourceWitness; 4] = [
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/nip17.rs",
- required_fragments: &["pub async fn radroots_nostr_unwrap_gift_wrap<T>("],
+ required_fragments: &["pub async fn unwrap_gift_wrap<T>("],
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/lib.rs",
@@ -2227,7 +2221,7 @@ const APP_HANDLER_WITNESSES: [EventBoundarySourceWitness; 2] = [
},
EventBoundarySourceWitness {
relative_path: "crates/nostr/src/events/application_handler.rs",
- required_fragments: &["pub fn radroots_nostr_build_application_handler_event("],
+ required_fragments: &["pub fn build_application_handler_event("],
},
];
@@ -2647,7 +2641,7 @@ const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [
EventBoundaryExpectation {
domain: "reply",
kind: "1",
- radroots_type: "AuthoredNip10Reply / RadrootsInboundNip10ReplyProjection / RadrootsAdmittedNip10ReplyEvent / RadrootsNostrNip10ReplyEventBuilder",
+ radroots_type: "AuthoredNip10Reply / RadrootsInboundNip10ReplyProjection / RadrootsAdmittedNip10ReplyEvent / Nip10ReplyBuilder",
rpc_methods: &[
"social.reply.build_authored_draft",
"social.reply.project_verified_event",
@@ -2658,7 +2652,7 @@ const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [
EventBoundaryExpectation {
domain: "comment",
kind: "1111",
- radroots_type: "AuthoredNip22Comment / RadrootsInboundNip22CommentProjection / RadrootsAdmittedNip22CommentEvent / RadrootsNostrNip22CommentEventBuilder",
+ radroots_type: "AuthoredNip22Comment / RadrootsInboundNip22CommentProjection / RadrootsAdmittedNip22CommentEvent / Nip22CommentBuilder",
rpc_methods: &[
"social.comment.build_authored_draft",
"social.comment.project_verified_event",
@@ -2669,7 +2663,7 @@ const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [
EventBoundaryExpectation {
domain: "deletion_request",
kind: "5",
- radroots_type: "AuthoredNip09DeletionRequest / RadrootsInboundNip09DeletionProjection / RadrootsAdmittedNip09DeletionRequestEvent / RadrootsNip09SuppressionDecision / RadrootsNostrNip09DeletionRequestEventBuilder",
+ radroots_type: "AuthoredNip09DeletionRequest / RadrootsInboundNip09DeletionProjection / RadrootsAdmittedNip09DeletionRequestEvent / RadrootsNip09SuppressionDecision / Nip09DeletionRequestBuilder",
rpc_methods: &[
"social.deletion_request.build_authored_draft",
"social.deletion_request.project_verified_event",
@@ -2947,7 +2941,7 @@ const CANONICAL_EVENT_BOUNDARY_EXPECTATIONS: [EventBoundaryExpectation; 44] = [
EventBoundaryExpectation {
domain: "food_availability",
kind: "30402",
- radroots_type: "FoodAvailabilityDetails / RadrootsInboundFoodAvailabilityProjection / RadrootsAdmittedFoodAvailabilityEvent / RadrootsNostrFoodAvailabilityEventBuilder",
+ radroots_type: "FoodAvailabilityDetails / RadrootsInboundFoodAvailabilityProjection / RadrootsAdmittedFoodAvailabilityEvent / FoodAvailabilityBuilder",
rpc_methods: &[
"food_availability.build_authored_draft",
"food_availability.project_verified_event",